-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: start PSM contracts with metrics, governance from previous published state #7480
Changes from all commits
56c9c39
d65b3bd
f5b4a30
743689c
e1774ff
54bc2dd
ea0c454
462e2c0
91aa63f
577bd25
2c03a0f
5a1ad92
d3fc98d
b65aa1f
b207ea5
6159b77
9615b01
9b1c8b6
4887e2a
d7b6e31
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,11 +1,13 @@ | ||||||
// @jessie-check | ||||||
|
||||||
import { makeMap } from 'jessie.js'; | ||||||
import { AmountMath, AssetKind } from '@agoric/ertp'; | ||||||
import { CONTRACT_ELECTORATE, ParamTypes } from '@agoric/governance'; | ||||||
import { makeStorageNodeChild } from '@agoric/internal/src/lib-chainStorage.js'; | ||||||
import { makeRatio } from '@agoric/zoe/src/contractSupport/index.js'; | ||||||
import { E } from '@endo/far'; | ||||||
import { Stable } from '@agoric/vats/src/tokens.js'; | ||||||
import { makeHistoryReviver } from '@agoric/vats/tools/board-utils.js'; | ||||||
import { deeplyFulfilledObject } from '@agoric/internal'; | ||||||
import { makeScalarMapStore } from '@agoric/vat-data'; | ||||||
|
||||||
|
@@ -18,24 +20,57 @@ import { | |||||
} from './committee-proposal.js'; | ||||||
|
||||||
/** @typedef {import('@agoric/vats/src/core/lib-boot.js').BootstrapManifest} BootstrapManifest */ | ||||||
/** @typedef {import('../psm/psm.js').MetricsNotification} MetricsNotification */ | ||||||
/** @typedef {import('./econ-behaviors.js').EconomyBootstrapPowers} EconomyBootstrapPowers */ | ||||||
|
||||||
const BASIS_POINTS = 10000n; | ||||||
const { details: X } = assert; | ||||||
|
||||||
export { inviteCommitteeMembers, startEconCharter, inviteToEconCharter }; | ||||||
|
||||||
const stablePsmKey = `published.psm.${Stable.symbol}`; | ||||||
|
||||||
/** | ||||||
* @param {Array<[key: string, value: string]>} chainStorageEntries | ||||||
* @param {string} keyword | ||||||
* @param {{ minted: Brand<'nat'>, anchor: Brand<'nat'> }} brands | ||||||
* @returns {{ metrics?: MetricsNotification, governance?: GovernanceSubscriptionState }} | ||||||
*/ | ||||||
const findOldPSMState = (chainStorageEntries, keyword, brands) => { | ||||||
// In this reviver, object references are revived as boardIDs | ||||||
// from the pre-bulldozer board. | ||||||
const toSlotReviver = makeHistoryReviver(chainStorageEntries); | ||||||
if (!toSlotReviver.has(`${stablePsmKey}.${keyword}.metrics`)) { | ||||||
return {}; | ||||||
} | ||||||
const metricsWithOldBoardIDs = toSlotReviver.getItem( | ||||||
`${stablePsmKey}.${keyword}.metrics`, | ||||||
); | ||||||
const oldIDtoNewBrand = makeMap([ | ||||||
[metricsWithOldBoardIDs.feePoolBalance.brand, brands.minted], | ||||||
[metricsWithOldBoardIDs.anchorPoolBalance.brand, brands.anchor], | ||||||
]); | ||||||
// revive brands; other object references map to undefined | ||||||
const brandReviver = makeHistoryReviver(chainStorageEntries, s => | ||||||
oldIDtoNewBrand.get(s), | ||||||
); | ||||||
return { | ||||||
metrics: brandReviver.getItem(`${stablePsmKey}.${keyword}.metrics`), | ||||||
governance: brandReviver.getItem(`${stablePsmKey}.${keyword}.governance`), | ||||||
}; | ||||||
}; | ||||||
|
||||||
/** | ||||||
* @param {EconomyBootstrapPowers & WellKnownSpaces} powers | ||||||
* @param {EconomyBootstrapPowers & WellKnownSpaces & ChainStorageVatParams} powers | ||||||
* @param {object} [config] | ||||||
* @param {bigint} [config.WantMintedFeeBP] | ||||||
* @param {bigint} [config.GiveMintedFeeBP] | ||||||
* @param {bigint} [config.MINT_LIMIT] | ||||||
* @param {{ anchorOptions?: AnchorOptions } } [config.options] | ||||||
* | ||||||
* @typedef {import('./econ-behaviors.js').EconomyBootstrapPowers} EconomyBootstrapPowers | ||||||
*/ | ||||||
export const startPSM = async ( | ||||||
{ | ||||||
vatParameters: { chainStorageEntries = [] }, | ||||||
consume: { | ||||||
agoricNamesAdmin, | ||||||
board, | ||||||
|
@@ -47,6 +82,7 @@ export const startPSM = async ( | |||||
chainStorage, | ||||||
chainTimerService, | ||||||
psmKit, | ||||||
anchorBalancePayments: anchorBalancePaymentsP, | ||||||
}, | ||||||
produce: { psmKit: producepsmKit }, | ||||||
installation: { | ||||||
|
@@ -97,6 +133,12 @@ export const startPSM = async ( | |||||
const mintLimit = AmountMath.make(minted, MINT_LIMIT); | ||||||
const anchorDecimalPlaces = anchorInfo.decimalPlaces || 1n; | ||||||
const mintedDecimalPlaces = mintedInfo.decimalPlaces || 1n; | ||||||
|
||||||
const oldState = findOldPSMState(chainStorageEntries, keyword, { | ||||||
minted, | ||||||
anchor: anchorBrand, | ||||||
}); | ||||||
|
||||||
const terms = await deeplyFulfilledObject( | ||||||
harden({ | ||||||
anchorBrand, | ||||||
|
@@ -107,10 +149,6 @@ export const startPSM = async ( | |||||
minted, | ||||||
), | ||||||
governedParams: { | ||||||
[CONTRACT_ELECTORATE]: { | ||||||
type: ParamTypes.INVITATION, | ||||||
value: electorateInvitationAmount, | ||||||
}, | ||||||
WantMintedFee: { | ||||||
type: ParamTypes.RATIO, | ||||||
value: makeRatio(WantMintedFeeBP, minted, BASIS_POINTS), | ||||||
|
@@ -120,10 +158,14 @@ export const startPSM = async ( | |||||
value: makeRatio(GiveMintedFeeBP, minted, BASIS_POINTS), | ||||||
}, | ||||||
MintLimit: { type: ParamTypes.AMOUNT, value: mintLimit }, | ||||||
}, | ||||||
[CONTRACT_ELECTORATE]: { | ||||||
type: ParamTypes.INVITATION, | ||||||
value: electorateInvitationAmount, | ||||||
// Override numeric config values from restored state. | ||||||
...oldState.governance?.current, | ||||||
// Don't override the invitation amount; | ||||||
// the electorate is re-constituted rather than restored. | ||||||
[CONTRACT_ELECTORATE]: { | ||||||
type: ParamTypes.INVITATION, | ||||||
value: electorateInvitationAmount, | ||||||
}, | ||||||
}, | ||||||
}), | ||||||
); | ||||||
|
@@ -170,6 +212,23 @@ export const startPSM = async ( | |||||
E(governorFacets.creatorFacet).getAdminFacet(), | ||||||
]); | ||||||
|
||||||
/** @param {MetricsNotification} metrics */ | ||||||
const restoreMetrics = async metrics => { | ||||||
const anchorBalancePayments = await anchorBalancePaymentsP; | ||||||
const anchorPmt = anchorBalancePayments.get(anchorBrand); | ||||||
|
||||||
const { anchorPoolBalance: _a, ...nonPaymentMetrics } = metrics; | ||||||
|
||||||
const seat = E(zoe).offer( | ||||||
E(psmCreatorFacet).makeRestoreMetricsInvitation(), | ||||||
harden({ give: { Anchor: metrics.anchorPoolBalance } }), | ||||||
harden({ Anchor: anchorPmt }), | ||||||
harden(nonPaymentMetrics), | ||||||
); | ||||||
await E(seat).getPayouts(); | ||||||
}; | ||||||
await (oldState.metrics && restoreMetrics(oldState.metrics)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why await first? we generally pass the promise in,
Suggested change
it's an async function so it can do the awaitiing,
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The idea is to
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oic. normally I'd expect, if (oldState.metrics) {
await restoreMetrics(oldState.metrics));
} but I suppose that trips on the jessie awaits rule |
||||||
|
||||||
/** @typedef {import('./econ-behaviors.js').PSMKit} psmKit */ | ||||||
/** @type {psmKit} */ | ||||||
const newpsmKit = { | ||||||
|
@@ -217,18 +276,25 @@ harden(startPSM); | |||||
* Make anchor issuer out of a Cosmos asset; presumably | ||||||
* USDC over IBC. Add it to BankManager. | ||||||
* | ||||||
* Also, if vatParameters shows an anchorPoolBalance for this asset, | ||||||
* mint a payment for that balance. | ||||||
* | ||||||
* TODO: address redundancy with publishInterchainAssetFromBank | ||||||
* | ||||||
* @param {EconomyBootstrapPowers & WellKnownSpaces} powers | ||||||
* @param {EconomyBootstrapPowers & WellKnownSpaces & ChainStorageVatParams} powers | ||||||
* @param {{options?: { anchorOptions?: AnchorOptions } }} [config] | ||||||
*/ | ||||||
export const makeAnchorAsset = async ( | ||||||
{ | ||||||
consume: { agoricNamesAdmin, bankManager, zoe }, | ||||||
vatParameters: { chainStorageEntries = [] }, | ||||||
consume: { agoricNamesAdmin, bankManager, zoe, anchorBalancePayments }, | ||||||
installation: { | ||||||
consume: { mintHolder }, | ||||||
}, | ||||||
produce: { testFirstAnchorKit }, | ||||||
produce: { | ||||||
testFirstAnchorKit, | ||||||
anchorBalancePayments: produceAnchorBalancePayments, | ||||||
}, | ||||||
}, | ||||||
{ options: { anchorOptions = {} } = {} }, | ||||||
) => { | ||||||
|
@@ -268,7 +334,23 @@ export const makeAnchorAsset = async ( | |||||
|
||||||
testFirstAnchorKit.resolve(kit); | ||||||
|
||||||
return Promise.all([ | ||||||
const toSlotReviver = makeHistoryReviver(chainStorageEntries); | ||||||
const metricsKey = `${stablePsmKey}.${keyword}.metrics`; | ||||||
if (toSlotReviver.has(metricsKey)) { | ||||||
const metrics = toSlotReviver.getItem(metricsKey); | ||||||
produceAnchorBalancePayments.resolve(makeScalarMapStore()); | ||||||
// XXX this rule should only apply to the 1st await | ||||||
// eslint-disable-next-line @jessie.js/no-nested-await | ||||||
const anchorPaymentMap = await anchorBalancePayments; | ||||||
|
||||||
// eslint-disable-next-line @jessie.js/no-nested-await | ||||||
const pmt = await E(mint).mintPayment( | ||||||
AmountMath.make(brand, metrics.anchorPoolBalance.value), | ||||||
); | ||||||
anchorPaymentMap.init(brand, pmt); | ||||||
} | ||||||
|
||||||
await Promise.all([ | ||||||
E(E(agoricNamesAdmin).lookupAdmin('issuer')).update(keyword, kit.issuer), | ||||||
E(E(agoricNamesAdmin).lookupAdmin('brand')).update(keyword, kit.brand), | ||||||
E(bankManager).addAsset( | ||||||
|
@@ -376,11 +458,18 @@ export const INVITE_PSM_COMMITTEE_MANIFEST = harden( | |||||
/** @type {BootstrapManifest} */ | ||||||
export const PSM_MANIFEST = { | ||||||
[makeAnchorAsset.name]: { | ||||||
consume: { agoricNamesAdmin: true, bankManager: 'bank', zoe: 'zoe' }, | ||||||
vatParameters: { chainStorageEntries: true }, | ||||||
consume: { | ||||||
agoricNamesAdmin: true, | ||||||
bankManager: 'bank', | ||||||
zoe: 'zoe', | ||||||
anchorBalancePayments: true, | ||||||
}, | ||||||
installation: { consume: { mintHolder: 'zoe' } }, | ||||||
produce: { testFirstAnchorKit: true }, | ||||||
produce: { testFirstAnchorKit: true, anchorBalancePayments: true }, | ||||||
}, | ||||||
[startPSM.name]: { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. incidentally, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. --- a/packages/vats/src/core/boot-psm.js
+++ b/packages/vats/src/core/boot-psm.js
@@ -221,7 +221,7 @@ export const buildRootObject = (vatPowers, vatParameters) => {
}),
),
...anchorAssets.map(anchorOptions =>
- startPSM(powersFor('startPSM'), {
+ startPSM(powersFor(startPSM.name), {
options: { anchorOptions },
}),
), |
||||||
vatParameters: { chainStorageEntries: true }, | ||||||
consume: { | ||||||
agoricNamesAdmin: true, | ||||||
board: true, | ||||||
|
@@ -392,6 +481,7 @@ export const PSM_MANIFEST = { | |||||
econCharterKit: 'econCommitteeCharter', | ||||||
chainTimerService: 'timer', | ||||||
psmKit: true, | ||||||
anchorBalancePayments: true, | ||||||
}, | ||||||
produce: { psmKit: 'true' }, | ||||||
installation: { | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs more docs on why
oldState.governance
isn't sufficient.