Skip to content
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

chore(pp-upgrade): test functionality after provisionPool and bank upgrade #10419

Merged
merged 4 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
replaceFeeDistributor/
testUpgradedBoard/
addUsdLemons/
upgradeProvisionPool/
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"consume": {
"contractKits": true,
"namesByAddressAdmin": true,
"agoricNames": true
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// @ts-nocheck
/* eslint-disable no-undef */
const PROVISIONING_POOL_ADDR = 'agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346';

const depositUsdLemons = async powers => {
const {
consume: {
contractKits: contractKitsP,
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 [contractKits, usdLemonsIssuer, usdLemonsBrand, ppDepositFacet] =
await Promise.all([
contractKitsP,
E(agoricNames).lookup('issuer', 'USD_LEMONS'),
E(agoricNames).lookup('brand', 'USD_LEMONS'),
getDepositFacet(PROVISIONING_POOL_ADDR),
]);

console.log('[CONTRACT_KITS]', contractKits);
console.log('[ISSUER]', usdLemonsIssuer);

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.');
};

depositUsdLemons;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"consume": {
"provisionPoolStartResult": true,
"instancePrivateArgs": true,
"economicCommitteeCreatorFacet": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// @ts-nocheck
/* eslint-disable no-undef */
const nullUpgradePP = async powers => {
const {
consume: {
provisionPoolStartResult: provisionPoolStartResultP,
instancePrivateArgs: instancePrivateArgsP,
economicCommitteeCreatorFacet,
},
} = powers;

console.log('awaiting powers');
const { adminFacet, instance } = await provisionPoolStartResultP;
const instancePrivateArgs = await instancePrivateArgsP;

console.log('get privateArgs');
const privateArgs = instancePrivateArgs.get(instance);
const [poolBank, poserInvitation] = await Promise.all([
privateArgs.poolBank,
E(economicCommitteeCreatorFacet).getPoserInvitation(),
]);

console.log('DEBUG', {
adminFacet,
instance,
privateArgs,
poserInvitation,
});

await E(adminFacet).restartContract({
...privateArgs,
poolBank,
initialPoserInvitation: poserInvitation,
});
console.log('Done');
};

nullUpgradePP;
3 changes: 3 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"type": "/agoric.swingset.CoreEvalProposal",
"sdk-generate": [
"testing/replace-feeDistributor-short.js replaceFeeDistributor",
"testing/add-USD-LEMONS.js addUsdLemons",
"vats/upgrade-provisionPool.js upgradeProvisionPool",
"vats/upgrade-paRegistry.js",
"vats/upgrade-board.js",
"testing/test-upgraded-board.js testUpgradedBoard"
Expand All @@ -13,6 +15,7 @@
"dependencies": {
"@agoric/client-utils": "0.1.1-dev-02c06c4.0",
"@agoric/ertp": "dev",
"@agoric/internal": "dev",
"@agoric/synthetic-chain": "^0.4.3",
"@agoric/zoe": "dev",
"@endo/errors": "1.2.7",
Expand Down
186 changes: 186 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/provisionPool.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();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* eslint-env node */
import { retryUntilCondition } from '@agoric/client-utils';
import {
addUser,
CHAINID,
makeAgd,
VALIDATORADDR,
} from '@agoric/synthetic-chain';
import { execFileSync } from 'node:child_process';

const agd = makeAgd({ execFileSync }).withOpts({ keyringBackend: 'test' });

/**
* @param {string} addr
* @param {string} wanted
* @param {string} [from]
*/
export const bankSend = (addr, wanted, from = VALIDATORADDR) => {
return agd.tx(['bank', 'send', from, addr, wanted], {
chainId: CHAINID,
from,
yes: true,
});
};

export const provision = (name, address) =>
agd.tx(['swingset', 'provision-one', name, address, 'SMART_WALLET'], {
chainId: 'agoriclocal',
from: 'validator',
yes: true,
});

export const introduceAndProvision = async name => {
const address = await addUser(name);
console.log('ADDR', name, address);

const provisionP = provision(name, address);

return { provisionP, address };
};

/**
* @param {import('@agoric/client-utils').VstorageKit} vstorageKit
*/
export const getProvisionedAddresses = async vstorageKit => {
const children = await vstorageKit.vstorage.keys('published.wallet');
return children;
};

export const checkUserProvisioned = (addr, vstorageKit) =>
retryUntilCondition(
() => getProvisionedAddresses(vstorageKit),
children => children.includes(addr),
'Account not provisioned',
{ maxRetries: 5, retryIntervalMs: 1000, log: console.log, setTimeout },
);
2 changes: 2 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@

yarn ava replaceFeeDistributor.test.js
yarn ava upgradedBoard.test.js

yarn ava provisionPool.test.js
7 changes: 6 additions & 1 deletion a3p-integration/proposals/p:upgrade-19/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@
"noImplicitThis": true,
// XXX synthetic-chain has some errors
"skipLibCheck": true
}
},
"exclude": [
"addUsdLemons/",
"replaceFeeDistributor/",
"upgradeProvisionPool/"
]
}
Loading
Loading