Skip to content

Commit

Permalink
feat: repair vaultUpgrade proposal; register scaledPriceAuthority
Browse files Browse the repository at this point in the history
replace scaledPriceAuthority
  • Loading branch information
Chris-Hibbert committed Jul 31, 2024
1 parent 20cb52f commit 0aa860e
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 87 deletions.
2 changes: 2 additions & 0 deletions golang/cosmos/app/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ func upgradePriceFeedCoreProposalSteps(upgradeName string) ([]vm.CoreProposalSte
return []vm.CoreProposalStep{
// Add new vats for price feeds. The existing ones will be retired shortly.
vm.CoreProposalStepForModules(proposals...),
// add new scaledPriceAuthorities. The existing ones will be retired shortly.
vm.CoreProposalStepForModules("@agoric/builders/scripts/vats/replaceScaledPriceAuthorities.js"),
// Add new auction contract. The old one will be retired shortly.
vm.CoreProposalStepForModules("@agoric/builders/scripts/vats/add-auction.js"),
// upgrade vaultFactory.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { makeHelpers } from '@agoric/deploy-script-support';
export const defaultProposalBuilder = async ({ publishRef, install }) =>
harden({
sourceSpec:
'@agoric/inter-protocol/src/proposals/upgrade-scaledPriceAuthorities.js',
'@agoric/inter-protocol/src/proposals/replace-scaledPriceAuthorities.js',
getManifestCall: [
'getManifestForUpgradeScaledPriceAuthorities',
'getManifestForReplaceScaledPriceAuthorities',
{
scaledPARef: publishRef(
install('@agoric/zoe/src/contracts/scaledPriceAuthority.js'),
Expand All @@ -18,5 +18,5 @@ export const defaultProposalBuilder = async ({ publishRef, install }) =>
export default async (homeP, endowments) => {
const { writeCoreEval } = await makeHelpers(homeP, endowments);

await writeCoreEval('upgradeScaledPriceAuthorities', defaultProposalBuilder);
await writeCoreEval('replaceScaledPriceAuthorities', defaultProposalBuilder);
};
3 changes: 2 additions & 1 deletion packages/inter-protocol/src/proposals/price-feed-proposal.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ export const createPriceFeed = async (

// being after the above awaits means that when this resolves, the consumer
// gets notified that the authority is in the registry and its instance is in
// agoricNames.
// agoricNames. reset() in case we're replacing an existing feed.
produceInstance[AGORIC_INSTANCE_NAME].reset();
produceInstance[AGORIC_INSTANCE_NAME].resolve(faKit.instance);

E(E.get(econCharterKit).creatorFacet).addInstance(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import { makeTracer, deeplyFulfilledObject } from '@agoric/internal';
import { E } from '@endo/far';
import { makeRatio } from '@agoric/zoe/src/contractSupport/index.js';
import { parseRatio } from '@agoric/zoe/src/contractSupport/ratio.js';

import { reserveThenGetNames, scaledPriceFeedName } from './utils.js';

const trace = makeTracer('replaceScaledPA', true);

/**
* Copied with minor modification from addAssetToVault.js because a previous
* scaledPriceAuthority is being replaced.
*
* @param {BootstrapPowers} powers
* @param {object} config
* @param {object} config.options
* @param {import('./addAssetToVault.js').InterchainAssetOptions} config.options.interchainAssetOptions
*/
export const replaceScaledPriceAuthority = async (
{
consume: {
agoricNamesAdmin,
startUpgradable,
priceAuthorityAdmin,
priceAuthority,
},
instance: { produce: produceInstance },
},
{ options: { interchainAssetOptions } },
) => {
const {
keyword,
issuerName = keyword,
oracleBrand = issuerName,
initialPrice: initialPriceRaw,
} = interchainAssetOptions;
assert.typeof(issuerName, 'string');
assert.typeof(oracleBrand, 'string');

const [
sourcePriceAuthority,
[interchainBrand, stableBrand],
[interchainOracleBrand, usdBrand],
[scaledPriceAuthority],
] = await Promise.all([
priceAuthority,
reserveThenGetNames(E(agoricNamesAdmin).lookupAdmin('brand'), [
issuerName,
'IST',
]),
reserveThenGetNames(E(agoricNamesAdmin).lookupAdmin('oracleBrand'), [
oracleBrand,
'USD',
]),
reserveThenGetNames(E(agoricNamesAdmin).lookupAdmin('installation'), [
'scaledPriceAuthority',
]),
]);

// We need "unit amounts" of each brand in order to get the ratios right. You
// can ignore decimalPlaces when adding and subtracting a brand with itself,
// but not when creating ratios.
const getDecimalP = async brand => {
const displayInfo = E(brand).getDisplayInfo();
return E.get(displayInfo).decimalPlaces;
};
const [
decimalPlacesInterchainOracle = 0,
decimalPlacesInterchain = 0,
decimalPlacesUsd = 0,
decimalPlacesRun = 0,
] = await Promise.all([
getDecimalP(interchainOracleBrand),
getDecimalP(interchainBrand),
getDecimalP(usdBrand),
getDecimalP(stableBrand),
]);

const scaleIn = makeRatio(
10n ** BigInt(decimalPlacesInterchainOracle),
interchainOracleBrand,
10n ** BigInt(decimalPlacesInterchain),
interchainBrand,
);
const scaleOut = makeRatio(
10n ** BigInt(decimalPlacesUsd),
usdBrand,
10n ** BigInt(decimalPlacesRun),
stableBrand,
);
const initialPrice = initialPriceRaw
? parseRatio(initialPriceRaw, stableBrand, interchainBrand)
: undefined;

const terms = await deeplyFulfilledObject(
harden({
sourcePriceAuthority,
scaleIn,
scaleOut,
initialPrice,
}),
);

const label = scaledPriceFeedName(issuerName);

const spaKit = await E(startUpgradable)({
installation: scaledPriceAuthority,
label,
terms,
});

// @ts-expect-error The public facet should have getPriceAuthority
const pa = await E(spaKit.publicFacet).getPriceAuthority();
trace(pa);

await E(priceAuthorityAdmin).registerPriceAuthority(
pa,
interchainBrand,
stableBrand,
true, // force
);

produceInstance[label].reset();
// publish into agoricNames so that others can await its presence.
// This must stay after registerPriceAuthority above so it's evidence of registration.

produceInstance[label].resolve(spaKit.instance);
};

/**
* Look up the existing assets known to auctions, and replace the corresponding
* scaledPriceAuthorities. The existing contracts will be left behind to be
* cleaned up later.
*
* @param {ChainBootstrapSpace & BootstrapPowers} powers
* @param {{ options: { scaledPARef: { bundleID: string } } }} options
*/
export const replaceScaledPriceAuthorities = async (powers, { options }) => {
trace('start');
const {
consume: {
agoricNamesAdmin,
contractKits: contractKitsP,
instancePrivateArgs: instancePrivateArgsP,
priceAuthority,
zoe,
},
} = powers;

const { scaledPARef } = options;
await null;

const bundleID = scaledPARef.bundleID;
if (scaledPARef && bundleID) {
await E.when(
E(zoe).installBundleID(bundleID),
installation =>
E(E(agoricNamesAdmin).lookupAdmin('installation')).update(
'scaledPriceAuthority',
installation,
),
err =>
console.error(
`🚨 failed to update scaledPriceAuthority installation`,
err,
),
);
trace('installed scaledPriceAuthority bundle', bundleID);
}

const [contractKits] = await Promise.all([
contractKitsP,
instancePrivateArgsP,
]);
/** @type {StartedInstanceKit<any>[]} */
const scaledPAKitEntries = Array.from(contractKits.values()).filter(
kit => kit.label && kit.label.match(/scaledPriceAuthority/),
);

const pa = await priceAuthority;
trace('priceAuthority', pa);

for (const kitEntry of scaledPAKitEntries) {
trace({ kitEntry });

const keyword = kitEntry.label.match(/scaledPriceAuthority-(.*)/)[1];
const interchainAssetOptions = { keyword };
await replaceScaledPriceAuthority(powers, {
options: { interchainAssetOptions },
});
}
};

const t = 'replaceScaledPriceAuthority';
export const getManifestForReplaceScaledPriceAuthorities = async (
_ign,
upgradeSPAOptions,
) => ({
manifest: {
[replaceScaledPriceAuthorities.name]: {
consume: {
agoricNamesAdmin: t,
contractKits: t,
instancePrivateArgs: t,
priceAuthority: t,
priceAuthorityAdmin: t,
zoe: t,
startUpgradable: t,
},
instance: {
produce: t,
},
},
},
options: { ...upgradeSPAOptions },
});

This file was deleted.

3 changes: 1 addition & 2 deletions packages/zoe/src/contractSupport/priceAuthority.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { q, Fail } from '@endo/errors';
import { E } from '@endo/eventual-send';
import { Far } from '@endo/marshal';
import { makePromiseKit } from '@endo/promise-kit';

import { AmountMath, AmountShape, BrandShape } from '@agoric/ertp';
import { makeNotifier } from '@agoric/notifier';
import { makeTracer } from '@agoric/internal';
Expand Down Expand Up @@ -259,7 +258,7 @@ export const makeOnewayPriceAuthorityKit = opts => {
};

/** @type {PriceAuthority} */
const priceAuthority = Far('PriceAuthority', {
const priceAuthority = Far('PriceAggregator', {
getQuoteIssuer(brandIn, brandOut) {
assertBrands(brandIn, brandOut);
return quoteIssuer;
Expand Down
2 changes: 1 addition & 1 deletion packages/zoe/src/contractSupport/priceAuthorityInitial.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export const makeInitialTransform = (
: quoteP;
};

return Far('PriceAuthority', {
return Far('ScaledPriceAuthority', {
...priceAuthority,
makeQuoteNotifier,
quoteGiven,
Expand Down
5 changes: 3 additions & 2 deletions packages/zoe/src/contracts/scaledPriceAuthority.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { provideQuoteMint } from '../contractSupport/priceAuthorityQuoteMint.js'
* via ratios.
*
* No durable state. Because it only transforms there's nothing important to save.
* However that also means that the contract terms cannot be modified and should
* However, that also means that the contract terms cannot be modified and should
* a `sourcePriceAuthority` reference sever this contract will break. A future version
* could allow changing that term through privateArgs or governance.
*
Expand All @@ -52,7 +52,8 @@ export const prepare = async (zcf, privateArgs, baggage) => {

const priceAuthority = makePriceAuthorityTransform({
quoteMint,
sourcePriceAuthority,
// If the priceAuthority is overridden in privateArgs, use that version
sourcePriceAuthority: privateArgs?.priceAuthority || sourcePriceAuthority,
sourceBrandIn,
sourceBrandOut,
actualBrandIn,
Expand Down

0 comments on commit 0aa860e

Please sign in to comment.