Skip to content

Commit

Permalink
test: audit contract flows in product spec (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
dckc committed Nov 26, 2024
1 parent ee4a817 commit 1757633
Showing 1 changed file with 71 additions and 13 deletions.
84 changes: 71 additions & 13 deletions packages/fast-usdc/test/fast-usdc.contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
import type { Instance } from '@agoric/zoe/src/zoeService/utils.js';
import { setUpZoeForTest } from '@agoric/zoe/tools/setup-zoe.js';
import { E } from '@endo/far';
import { objectMap } from '@endo/patterns';
import { matches, objectMap } from '@endo/patterns';
import path from 'path';
import type { ScopedBridgeManager } from '@agoric/vats';
import { makePromiseKit } from '@endo/promise-kit';
Expand All @@ -36,6 +36,7 @@ import { addressTools } from '../src/utils/address.js';
import { makeFeeTools } from '../src/utils/fees.js';
import { MockCctpTxEvidences } from './fixtures.js';
import { commonSetup } from './supports.js';
import { PoolMetricsShape } from '../src/type-guards.js';

const dirname = path.dirname(new URL(import.meta.url).pathname);

Expand Down Expand Up @@ -618,6 +619,9 @@ const makeCustomer = (
) => {
const evidence = sent.shift();
if (!evidence) throw t.fail('nothing sent');

// C3 - Contract MUST calculate AdvanceAmount by ...
// Mostly, see unit tests for calculateAdvance, calculateSplit
const toReceive = forward
? { value: evidence.tx.amount }
: feeTools.calculateAdvance(AmountMath.make(USDC, evidence.tx.amount));
Expand All @@ -630,6 +634,7 @@ const makeCustomer = (
const { EUD } = addressTools.getQueryParams(
evidence.aux.recipientAddress,
);

const myMsg = local.find(lm => {
if (lm.type !== 'VLOCALCHAIN_EXECUTE_TX') return false;
const [ibcTransferMsg] = lm.messages;
Expand All @@ -644,10 +649,14 @@ const makeCustomer = (
throw t.fail(`no MsgTransfer to ${EUD}`);
}
const [ibcTransferMsg] = myMsg.messages;
t.deepEqual(ibcTransferMsg.token, {
amount: String(toReceive.value),
denom: uusdcOnAgoric,
});
// C4 - Contract MUST release funds to the end user destination address
// in response to invocation by the off-chain watcher that
// an acceptable Fast USDC Transaction has been initiated.
t.deepEqual(
ibcTransferMsg.token,
{ amount: String(toReceive.value), denom: uusdcOnAgoric },
'C4',
);

t.log(who, 'sees', ibcTransferMsg.token, 'sent to', EUD);
// TODO #10445 expect PFM memo
Expand Down Expand Up @@ -683,7 +692,20 @@ test.serial('OCW operators redeem invitations and start watching', async t => {

// TODO: replace test.serial() with promise synchronization?

test.serial('customer tries before LPs provide liquidity', async t => {
test.serial('STORY09: Fast USDC off: insufficient liquidity', async t => {
const {
common: {
commonPrivateArgs: { feeConfig },
},
evm: { cctp, txPub },
startKit: { metricsSub },
} = t.context;
const early = makeCustomer('Unice', cctp, txPub.publisher, feeConfig, t);
const available = await early.checkPoolAvailable(5_000_000n, metricsSub);
t.false(available);
});

test.serial('C20 - customer tries before LPs provide liquidity', async t => {
const {
common: {
commonPrivateArgs: { feeConfig },
Expand All @@ -708,7 +730,7 @@ test.serial('customer tries before LPs provide liquidity', async t => {
// fulfilled" in the test output.
});

test.serial('LPs deposit USDC', async t => {
test.serial('C25 - LPs deposit USDC', async t => {
const {
startKit: { zoe, instance, metricsSub },
common: {
Expand All @@ -718,6 +740,7 @@ test.serial('LPs deposit USDC', async t => {
sync,
} = t.context;
const usdcPurse = purseOf(usdc.issuer, utils);
// C25 - MUST support multiple liquidity providers
const lp = {
lp50: makeLP('Logan', usdcPurse(50_000_000n), zoe, instance, t),
lp200: makeLP('Larry', usdcPurse(200_000_000n), zoe, instance, t),
Expand All @@ -743,7 +766,7 @@ test.serial('LPs deposit USDC', async t => {
t.deepEqual(poolBalance, make(usdc.brand, 250_000_000n + balance0.value));
});

test.serial('advancing happy path for 100 USDC', async t => {
test.serial('STORY01: advancing happy path for 100 USDC', async t => {
const {
common: {
brands: { usdc },
Expand Down Expand Up @@ -804,6 +827,10 @@ test.serial('advancing happy path for 100 USDC', async t => {

await mint(sent1);

// C8 - "Contract MUST be able to initialize settlement process when Noble mints USDC."
// The metrics are a useful proxy, but the contract could lie.
// The real test of whether the contract turns minted funds into liquidity is
// the ability to advance the funds (in later tests).
const split = calculateSplit(usdc.make(sent1.tx.amount));
t.like(
await E(metricsSub)
Expand All @@ -824,20 +851,44 @@ test.serial('advancing happy path for 100 USDC', async t => {
);
});

test.serial('LP withdraws part; collects fees on 100 USDC', async t => {
test.todo(
'PERF: Target: settlement completes in a few minutes (after USDC is minted)',
);

// most likely in exo unit tests
test.todo(
'C21 - Contract MUST log / timestamp each step in the transaction flow',
);

test.serial('STORY03: see accounting metrics', async t => {
const {
sync,
common: {
brands: { usdc },
commonPrivateArgs: { feeConfig },
},
startKit: { metricsSub },
} = t.context;
const { value: metrics } = await E(metricsSub).getUpdateSince();

const { calculateSplit } = makeFeeTools(feeConfig);
const split = calculateSplit(usdc.make(100_000_000n));
t.log(metrics);
t.true(matches(metrics, PoolMetricsShape));
});
test.todo('document metrics storage schema');
test.todo('get metrics from vstorage');

test.serial('STORY05: LP collects fees on 100 USDC', async t => {
const {
sync,
common: {
brands: { usdc },
},
} = t.context;

const lp = await sync.lp.promise;
const got = await E(lp.lp200).withdraw(0.5); // redeem 1/2 my shares

// C3 - Contract MUST calculate ...
// Mostly, see unit tests for calculateAdvance, calculateSplit
// TODO: add a feeTools unit test for the magic number below.
t.deepEqual(got, add(usdc.units(100), usdc.make(691_200n)));

await E(lp.lp200).deposit(100_000_000n); // put all but the fees back in
Expand Down Expand Up @@ -879,6 +930,13 @@ test.serial('racers', async t => {
await Promise.all([mint(sent1), mint(sent2), mint(sent3)]);
});

// advancedEarly stuff
test.todo(
'C12 - Contract MUST only pay back the Pool only if they started the advance before USDC is minted',
);

test.todo('C18 - forward - MUST log and alert these incidents');

test.serial('Settlement for unknown transaction (operator down)', async t => {
const {
sync,
Expand Down

0 comments on commit 1757633

Please sign in to comment.