Skip to content

Commit

Permalink
test(a3p): add mintHolder upgrade test and helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
Jorge-Lopes committed Dec 10, 2024
1 parent c1ae023 commit 4468330
Show file tree
Hide file tree
Showing 6 changed files with 438 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* global E */

/// <reference types="@agoric/vats/src/core/core-eval-env"/>
/// <reference types="@agoric/vats/src/core/types-ambient"/>

/**
* The primary purpose of this script is to mint a payment of a certain
* bankAsset and deposit in an user wallet.
*
* The receiverAddress and label placeholders should be replaced with
* the desired address and asset name during the execution of each test case.
*
* See z:acceptance/mintHolder.test.js
*
* @param {BootstrapPowers} powers
*/
const sendBankAsset = async powers => {
const {
consume: { namesByAddress, contractKits: contractKitsP },
} = powers;

const receiverAddress = '{{ADDRESS}}';
const label = '{{LABEL}}';
const valueStr = '{{VALUE}}';
const value = BigInt(valueStr)

console.log(`Start sendBankAsset for ${label}`);

const contractKits = await contractKitsP;
const mintHolderKit = Array.from(contractKits.values()).filter(
kit => kit.label && kit.label === label,
);

const { creatorFacet: mint, publicFacet: issuer } = mintHolderKit[0];

/*
* Ensure that publicFacet holds an issuer by verifying that has
* the makeEmptyPurse method.
*/
await E(issuer).makeEmptyPurse()

const brand = await E(issuer).getBrand();
const amount = harden({ value, brand });
const payment = await E(mint).mintPayment(amount);

const receiverDepositFacet = E(namesByAddress).lookup(
receiverAddress,
'depositFacet',
);

await E(receiverDepositFacet).receive(payment);

console.log(`Finished sendBankAsset for ${label}`);
};

sendBankAsset;
32 changes: 32 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/mintHolder.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* eslint-env node */

import '@endo/init';
import test from 'ava';
import { addUser, provisionSmartWallet } from '@agoric/synthetic-chain';
import {
mintPayment,
getAssetList,
swap,
getPSMChildren,
upgradeMintHolder,
} from './test-lib/mintHolder-helpers.js';

const networkConfig = {
rpcAddrs: ['http://0.0.0.0:26657'],
chainName: 'agoriclocal',
};

test('mintHolder contract is upgraded', async t => {
const receiver = await addUser('receiver');
await provisionSmartWallet(receiver, `20000000ubld`);

let assetList = await getAssetList();
t.log('List of mintHolder vats being upgraded: ', assetList);
await upgradeMintHolder(`upgrade-mintHolder`, assetList);
await mintPayment(t, receiver, assetList, 10);

const psmLabelList = await getPSMChildren(fetch, networkConfig);
assetList = await getAssetList(psmLabelList);
t.log('List of assets being swapped with IST via PSM: ', assetList);
await swap(t, receiver, assetList, 5);
});
156 changes: 156 additions & 0 deletions a3p-integration/proposals/p:upgrade-19/test-lib/mintHolder-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/* eslint-env node */

import {
agoric,
evalBundles,
getDetailsMatchingVats,
getISTBalance,
} from '@agoric/synthetic-chain';
import { makeVstorageKit, retryUntilCondition } from '@agoric/client-utils';
import { readFile, writeFile } from 'node:fs/promises';
import { sendOfferAgd, psmSwap, snapshotAgoricNames } from './psm-helpers.js';

/**
* @param {string} fileName base file name without .tjs extension
* @param {Record<string, string>} replacements
*/
export const replaceTemplateValuesInFile = async (fileName, replacements) => {
let script = await readFile(`${fileName}.tjs`, 'utf-8');
for (const [template, value] of Object.entries(replacements)) {
script = script.replaceAll(`{{${template}}}`, value);
}
await writeFile(`${fileName}.js`, script);
};

export const getPSMChildren = async (fetch, networkConfig) => {
const {
vstorage: { keys },
} = await makeVstorageKit({ fetch }, networkConfig);

const children = await keys('published.psm.IST');

return children;
};

export const getAssetList = async labelList => {
const assetList = [];
const { vbankAssets } = await snapshotAgoricNames();

// Determine the assets to consider based on labelList
const assetsToConsider =
labelList || Object.values(vbankAssets).map(asset => asset.issuerName);

for (const label of assetsToConsider) {
if (label === 'IST') {
break;
}

const vbankAsset = Object.values(vbankAssets).find(
asset => asset.issuerName === label,
);
assert(vbankAsset, `vbankAsset not found for ${label}`);

const { denom } = vbankAsset;
const mintHolderVat = `zcf-mintHolder-${label}`;

assetList.push({ label, denom, mintHolderVat });
}

return assetList;
};

export const mintPayment = async (t, address, assetList, value) => {
const SUBMISSION_DIR = 'mint-payment';

for (const asset of assetList) {
const { label, denom } = asset;
const scaled = BigInt(parseInt(value, 10) * 1_000_000).toString();

await replaceTemplateValuesInFile(`${SUBMISSION_DIR}/send-script`, {
ADDRESS: address,
LABEL: label,
VALUE: scaled,
});

await evalBundles(SUBMISSION_DIR);

const balance = await getISTBalance(address, denom);

// Add to value the BLD provisioned to smart wallet
if (label === 'BLD') {
value += 10;
}

t.is(
balance,
value,
`receiver ${denom} balance ${balance} is not ${value}`,
);
}
};

export const swap = async (t, address, assetList, want) => {
for (const asset of assetList) {
const { label, denom } = asset;

// TODO: remove condition after fixing issue #10655
if (/^DAI/.test(label)) {
break;
}

const pair = `IST.${label}`;

const istBalanceBefore = await getISTBalance(address, 'uist');
const anchorBalanceBefore = await getISTBalance(address, denom);

await psmSwap(address, ['swap', '--pair', pair, '--wantMinted', want], {
now: Date.now,
follow: agoric.follow,
setTimeout,
sendOffer: sendOfferAgd,
});

const istBalanceAfter = await getISTBalance(address, 'uist');
const anchorBalanceAfter = await getISTBalance(address, denom);

t.is(istBalanceAfter, istBalanceBefore + want);
t.is(anchorBalanceAfter, anchorBalanceBefore - want);
}
};

const getIncarnationForAllVats = async assetList => {
const vatsIncarnation = {};

for (const asset of assetList) {
const { label, mintHolderVat } = asset;
const matchingVats = await getDetailsMatchingVats(label);
const expectedVat = matchingVats.find(vat => vat.vatName === mintHolderVat);
vatsIncarnation[label] = expectedVat.incarnation;
}
assert(Object.keys(vatsIncarnation).length === assetList.length);

return vatsIncarnation;
};

const checkVatsUpgraded = (before, current) => {
for (const vatLabel in before) {
if (current[vatLabel] !== before[vatLabel] + 1) {
console.log(`${vatLabel} upgrade failed. `);
return false;
}
}
return true;
};

export const upgradeMintHolder = async (submissionPath, assetList) => {
const before = await getIncarnationForAllVats(assetList);

await evalBundles(submissionPath);

return retryUntilCondition(
async () => getIncarnationForAllVats(assetList),
current => checkVatsUpgraded(before, current),
`mintHolder upgrade not processed yet`,
{ setTimeout, retryIntervalMs: 5000, maxRetries: 15 },
);
};
Loading

0 comments on commit 4468330

Please sign in to comment.