Skip to content

Commit

Permalink
WIP: push up proposal and attempts at a test
Browse files Browse the repository at this point in the history
  • Loading branch information
iomekam committed Dec 6, 2024
1 parent e596a01 commit ebbfa73
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"consume": {
"reserveKit": true,
"namesByAddressAdmin": true,
"agoricNames": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// @ts-nocheck
/* eslint-disable no-undef */
const PROVISIONING_POOL_ADDR = 'agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346';

const addCollateral = async powers => {
const {
consume: {
reserveKit: reserveKitP,
namesByAddressAdmin: namesByAddressAdminP,
agoricNames,
},
} = powers;

const namesByAddressAdmin = await namesByAddressAdminP;

const getDepositFacet = async address => {
const hub = E(E(namesByAddressAdmin).lookupAdmin(address)).readonly();
return E(hub).lookup('depositFacet');
};

const [reserveKit] = await Promise.all([reserveKitP]);

const { adminFacet, instance } = reserveKit;

let usdLemonsMint;
for (const { publicFacet, creatorFacet: mint } of contractKits.values()) {
if (publicFacet === usdLemonsIssuer) {
usdLemonsMint = mint;
console.log('BINGO', mint);
break;
}
}

console.log('Minting USD_LEMONS');
const helloPayment = await E(usdLemonsMint).mintPayment(
harden({ brand: usdLemonsBrand, value: 500000n }),
);

console.log('Funding provision pool...');
await E(ppDepositFacet).receive(helloPayment);

console.log('Done.');
};

addCollateral;
186 changes: 186 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/assetReserve.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/* eslint-env node */
/**
* @file The goal of this file is to make sure v28-provisionPool and v14-bank can be successfully
* upgraded. These vats are related because of the issues below;
* - https://github.com/Agoric/agoric-sdk/issues/8722
* - https://github.com/Agoric/agoric-sdk/issues/8724
*
* The test scenario is as follows;
* 1. Upgrade provisionPool. This upgrade overrides provisionWalletBridgerManager with a durable one
* 2. Add a new account and successfully provision it
* - Observe new account's address under `published.wallet.${address}`
* 3. Send some USDC_axl to provisionPoolAddress and observe its IST balances increases accordingly
* 4. Introduce a new asset to the chain and start a PSM instance for the new asset
* 4a. Deposit some of that asset to provisionPoolAddress
* 4b. Observe provisionPoolAddress' IST balance increase by the amount deposited in step 4a
* 5. Perform a null upgrade for provisionPool. This upgrade does NOT override provisionWalletBridgerManager
* - The goal here is to allow testing the bridgeHandler from the first upgrade is in fact durable
* 6. Auto provision
* 6a. Introduce a new account
* 6b. Fund it with IST and ATOM to be able to open a vault
* 6c. Try to open a vault WITHOUT provisioning the newly introduced account
* 6d. Observe the new account's address under `published.wallet`
* 7. Same as step 2. Checks manual provision works after null upgrade
*/

import '@endo/init';
import test from 'ava';
import {
addUser,
evalBundles,
agd as agdAmbient,
agoric,
getISTBalance,
getDetailsMatchingVats,
GOV1ADDR,
openVault,
ATOM_DENOM,
} from '@agoric/synthetic-chain';
import {
makeVstorageKit,
waitUntilAccountFunded,
waitUntilContractDeployed,
} from '@agoric/client-utils';
import { NonNullish } from '@agoric/internal';
import {
bankSend,
checkUserProvisioned,
introduceAndProvision,
provision,
} from './test-lib/provision-helpers.js';

const PROVISIONING_POOL_ADDR = 'agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346';

const ADD_PSM_DIR = 'addUsdLemons';
const DEPOSIT_USD_LEMONS_DIR = 'depositUSD-LEMONS';
const UPGRADE_PP_DIR = 'upgradeProvisionPool';
const NULL_UPGRADE_PP_DIR = 'nullUpgradePP';

const USDC_DENOM = NonNullish(process.env.USDC_DENOM);

const ambientAuthority = {
query: agdAmbient.query,
follow: agoric.follow,
setTimeout,
log: console.log,
};

test.before(async t => {
const vstorageKit = await makeVstorageKit(
{ fetch },
{ rpcAddrs: ['http://localhost:26657'], chainName: 'agoriclocal' },
);

t.context = {
vstorageKit,
};
});

test.serial('upgrade provisionPool', async t => {
await evalBundles(UPGRADE_PP_DIR);

const vatDetailsAfter = await getDetailsMatchingVats('provisionPool');
const { incarnation } = vatDetailsAfter.find(vat =>
vat.vatName.endsWith('provisionPool'),
);

t.log(vatDetailsAfter);
t.is(incarnation, 1, 'incorrect incarnation');
t.pass();
});

test.serial(
`check provisionPool can recover purse and asset subscribers after upgrade`,
async t => {
// @ts-expect-error casting
const { vstorageKit } = t.context;

// Introduce new user then provision
const { address } = await introduceAndProvision('provisionTester');
await checkUserProvisioned(address, vstorageKit);

// Send USDC_axl to pp
const istBalanceBefore = await getISTBalance(PROVISIONING_POOL_ADDR);
await bankSend(PROVISIONING_POOL_ADDR, `500000${USDC_DENOM}`);

// Check IST balance
await waitUntilAccountFunded(
PROVISIONING_POOL_ADDR,
ambientAuthority,
{ denom: 'uist', value: istBalanceBefore + 500000 },
{ errorMessage: 'Provision pool not able to swap USDC_axl for IST.' },
);

// Introduce USD_LEMONS
await evalBundles(ADD_PSM_DIR);
await waitUntilContractDeployed('psm-IST-USD_LEMONS', ambientAuthority, {
errorMessage: 'psm-IST-USD_LEMONS instance not observed.',
});

// Provision the provisionPoolAddress. This is a workaround of provisionPoolAddress
// not having a depositFacet published to namesByAddress. Shouldn't be a problem since
// vat-bank keeps track of virtual purses per address basis. We need there to be
// depositFacet for provisionPoolAddress since we'll fund it with USD_LEMONS
await provision('provisionPoolAddress', PROVISIONING_POOL_ADDR);
await checkUserProvisioned(PROVISIONING_POOL_ADDR, vstorageKit);

// Send USD_LEMONS to provisionPoolAddress
const istBalanceBeforeLemonsSent = await getISTBalance(
PROVISIONING_POOL_ADDR,
);
await evalBundles(DEPOSIT_USD_LEMONS_DIR);

// Check balance again
await waitUntilAccountFunded(
PROVISIONING_POOL_ADDR,
ambientAuthority,
{ denom: 'uist', value: istBalanceBeforeLemonsSent + 500000 },
{ errorMessage: 'Provision pool not able to swap USDC_axl for IST.' },
);
t.pass();
},
);

test.serial('null upgrade', async t => {
await evalBundles(NULL_UPGRADE_PP_DIR);

const vatDetailsAfter = await getDetailsMatchingVats('provisionPool');
const { incarnation } = vatDetailsAfter.find(vat => vat.vatID === 'v28'); // provisionPool is v28

t.log(vatDetailsAfter);
t.is(incarnation, 2, 'incorrect incarnation');
t.pass();
});

test.serial('auto provision', async t => {
// @ts-expect-error casting
const { vstorageKit } = t.context;

const address = await addUser('automaticallyProvisioned');
console.log('ADDR', 'automaticallyProvisioned', address);

await bankSend(address, `50000000${ATOM_DENOM}`);
// some ist is needed for opening a new vault
await bankSend(address, `10000000uist`, GOV1ADDR);
await waitUntilAccountFunded(
address,
// TODO: drop agd.query and switch to vstorgeKit
{ log: console.log, setTimeout, query: agdAmbient.query },
{ denom: ATOM_DENOM, value: 50_000_000 },
{ errorMessage: `not able to fund ${address}` },
);

await openVault(address, '10.0', '20.0');
await checkUserProvisioned(address, vstorageKit);
t.pass();
});

test.serial('manual provision', async t => {
// @ts-expect-error casting
const { vstorageKit } = t.context;

const { address } = await introduceAndProvision('manuallyProvisioned');
await checkUserProvisioned(address, vstorageKit);
t.log('manuallyProvisioned address:', address);
t.pass();
});
15 changes: 15 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/upgradeAssetReserve.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* eslint-env node */
// @ts-check

/** @file test that the upgraded board can store and retrieve values. */

import '@endo/init/legacy.js';
import test from 'ava';
import { evalBundles } from '@agoric/synthetic-chain';

test('test upgraded board', async t => {
// agoricProposal.sdk-generate in package.json generates this proposal
await evalBundles('testUpgradedBoard');

t.pass();
});
21 changes: 21 additions & 0 deletions packages/builders/scripts/vats/upgrade-asset-reserve.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { makeHelpers } from '@agoric/deploy-script-support';

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').CoreEvalBuilder} */
export const defaultProposalBuilder = async ({ publishRef, install }) =>
harden({
sourceSpec: '@agoric/vats/src/proposals/upgrade-asset-reserve-proposal.js',
getManifestCall: [
'getManifestForUpgradingAssetReserve',
{
assetReserveRef: publishRef(
install('@agoric/inter-protocol/src/reserve/assetReserve.js'),
),
},
],
});

/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').DeployScriptFunction} */
export default async (homeP, endowments) => {
const { writeCoreProposal } = await makeHelpers(homeP, endowments);
await writeCoreProposal('upgrade-asset-reserve', defaultProposalBuilder);
};
2 changes: 1 addition & 1 deletion packages/vats/src/core/startWalletFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export const startWalletFactory = async (
},
});
provisionPoolStartResult.resolve(ppFacets);
instanceProduce.provisionPool.resolve(ppFacets.instance);
instanceProduce.reserve. .provisionPool.resolve(ppFacets.instance);

const terms = await deeplyFulfilled(
harden({
Expand Down
74 changes: 74 additions & 0 deletions packages/vats/src/proposals/upgrade-asset-reserve-proposal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { E } from '@endo/far';
import { deeplyFulfilled } from '@endo/marshal';
import { makeTracer } from '@agoric/internal';

const tracer = makeTracer('UpgradeAssetReserve');

/**
* @param {BootstrapPowers & {
* consume: {
* economicCommitteeCreatorFacet: any;
* reserveKit: any;
* };
* }} powers
* @param {object} options
* @param {{ assetReserveRef: VatSourceRef }} options.options
*/
export const upgradeAssetReserve = async (
{
consume: {
economicCommitteeCreatorFacet: electorateCreatorFacet,
reserveKit: reserveKitP,
instancePrivateArgs: instancePrivateArgsP,
},
},
options,
) => {
const { assetReserveRef } = options.options;

assert(assetReserveRef.bundleID);
tracer(`ASSET RESERBE BUNDLE ID: `, assetReserveRef);

const [reserveKit, instancePrivateArgs] = await Promise.all([
reserveKitP,
instancePrivateArgsP,
]);
const { adminFacet, instance } = reserveKit;

const [originalPrivateArgs, poserInvitation] = await Promise.all([
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore Local tsc sees this as an error but typedoc does not
deeplyFulfilled(instancePrivateArgs.get(instance)),
E(electorateCreatorFacet).getPoserInvitation(),
]);

const newPrivateArgs = harden({
...originalPrivateArgs,
initialPoserInvitation: poserInvitation,
});

const upgradeResult = await E(adminFacet).upgradeContract(
assetReserveRef.bundleID,
newPrivateArgs,
);

tracer('AssetReserve upgraded: ', upgradeResult);
tracer('Done.');
};

export const getManifestForUpgradingAssetReserve = (
_powers,
{ assetReserveRef },
) => ({
manifest: {
[upgradeAssetReserve.name]: {
consume: {
economicCommitteeCreatorFacet: true,
instancePrivateArgs: true,
reserveKit: true,
},
produce: {},
},
},
options: { assetReserveRef },
});

0 comments on commit ebbfa73

Please sign in to comment.