-
Notifications
You must be signed in to change notification settings - Fork 214
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(acceptance): add tests for PSM to
z:acceptance
Refs: Agoric/BytePitchPartnerEng#23 fix(acceptance-psm): address change requests
- Loading branch information
1 parent
2ca7ea6
commit 712f970
Showing
8 changed files
with
1,253 additions
and
366 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,274 @@ | ||
/* eslint-env node */ | ||
/** | ||
* @file The goal of this file is to implement a set of tests to make sure PSM works properly | ||
* | ||
* Here are the steps we want to take; | ||
* 1 - Change swap fees and mint limit according to "psmTestSpecs" below | ||
* 2 - Create a new user using agd.keys | ||
* 3 - Fund new user with a stable coin from the VALIDATOR | ||
* - Do not provision manually | ||
* 4 - Make sure new user is able to mint IST from PSM (fees are applied) | ||
* 5 - Make sure new user can pay their debt and get their anchor (fees are applied) | ||
* 6 - Make sure mint limit is adhered | ||
*/ | ||
|
||
import test from 'ava'; | ||
import { | ||
getUser, | ||
GOV1ADDR, | ||
GOV2ADDR, | ||
GOV3ADDR, | ||
waitForBlock, | ||
} from '@agoric/synthetic-chain'; | ||
import { | ||
adjustBalancesIfNotProvisioned, | ||
agopsPsm, | ||
bankSend, | ||
checkGovParams, | ||
checkSwapExceedMintLimit, | ||
checkSwapSucceeded, | ||
checkUserInitializedSuccessfully, | ||
getPsmMetrics, | ||
implementPsmGovParamChange, | ||
initializeNewUser, | ||
maxMintBelowLimit, | ||
} from './test-lib/psm-lib.js'; | ||
import { getBalances } from './test-lib/utils.js'; | ||
|
||
// Export these from synthetic-chain? | ||
export const USDC_DENOM = process.env.USDC_DENOM | ||
? process.env.USDC_DENOM | ||
: 'no-denom'; | ||
export const PSM_PAIR = process.env.PSM_PAIR?.replace('.', '-'); | ||
|
||
const psmTestSpecs = { | ||
govParams: { | ||
giveMintedFeeVal: 10n, // in % | ||
wantMintedFeeVal: 10n, // in % | ||
mintLimit: 500n * 1_000_000n, // in IST | ||
deadline: 1, // in minutes | ||
}, | ||
psmInstance: `psm-${PSM_PAIR}`, | ||
// @ts-expect-error we assume PSM_PAIR is set because of synthetic-chain environment | ||
anchor: PSM_PAIR.split('-')[1], | ||
newUser: { | ||
name: 'new-psm-trader', | ||
fund: { | ||
denom: USDC_DENOM, | ||
value: '300000000', // 300 USDC_axl | ||
}, | ||
}, | ||
otherUser: { | ||
name: 'gov1', | ||
fund: { | ||
denom: USDC_DENOM, | ||
value: '1000000000', // 1000 USDC_axl | ||
}, | ||
toIst: { | ||
value: 500, // in IST | ||
}, | ||
}, | ||
toIst: { | ||
value: 50, // in IST | ||
}, | ||
fromIst: { | ||
value: 50, // in USDC_axl | ||
}, | ||
}; | ||
|
||
test.serial('change gov params', async t => { | ||
await implementPsmGovParamChange( | ||
{ | ||
address: GOV1ADDR, | ||
instanceName: psmTestSpecs.psmInstance, | ||
newParams: psmTestSpecs.govParams, | ||
deadline: psmTestSpecs.govParams.deadline, | ||
}, | ||
{ committeeAddrs: [GOV1ADDR, GOV2ADDR, GOV3ADDR], position: 0 }, | ||
); | ||
|
||
// Replace when https://github.com/Agoric/agoric-sdk/pull/10171 is in | ||
await waitForBlock(3); | ||
await checkGovParams( | ||
t, | ||
{ | ||
GiveMintedFee: { | ||
type: 'ratio', | ||
value: { | ||
numerator: { value: psmTestSpecs.govParams.giveMintedFeeVal * 100n }, // convert to bps | ||
}, | ||
}, | ||
WantMintedFee: { | ||
type: 'ratio', | ||
value: { | ||
numerator: { value: psmTestSpecs.govParams.wantMintedFeeVal * 100n }, // convert to bps | ||
}, | ||
}, | ||
MintLimit: { | ||
type: 'amount', | ||
value: { | ||
value: psmTestSpecs.govParams.mintLimit, | ||
}, | ||
}, | ||
}, | ||
psmTestSpecs.psmInstance.split('-')[2], | ||
); | ||
}); | ||
|
||
test.serial('initialize new user', async t => { | ||
const { | ||
newUser: { name, fund }, | ||
} = psmTestSpecs; | ||
|
||
await initializeNewUser(name, fund); | ||
// Replace when https://github.com/Agoric/agoric-sdk/pull/10171 is in | ||
await waitForBlock(3); | ||
|
||
await checkUserInitializedSuccessfully(name, fund); | ||
t.pass(); | ||
}); | ||
|
||
test.serial('swap into IST', async t => { | ||
const { | ||
newUser: { name }, | ||
anchor, | ||
toIst, | ||
govParams: { wantMintedFeeVal }, | ||
} = psmTestSpecs; | ||
|
||
const psmTrader = await getUser(name); | ||
|
||
const [metricsBefore, balances] = await Promise.all([ | ||
getPsmMetrics(anchor), | ||
getBalances([psmTrader]), | ||
]); | ||
|
||
const balancesBefore = await adjustBalancesIfNotProvisioned( | ||
balances, | ||
psmTrader, | ||
); | ||
t.log('METRICS', metricsBefore); | ||
t.log('BALANCES', balancesBefore); | ||
|
||
await agopsPsm(psmTrader, [ | ||
'swap', | ||
'--pair', | ||
process.env.PSM_PAIR, | ||
'--wantMinted', | ||
toIst.value, | ||
'--feePct', | ||
wantMintedFeeVal, | ||
]); | ||
await waitForBlock(5); | ||
|
||
await checkSwapSucceeded(t, metricsBefore, balancesBefore, { | ||
wantMinted: toIst.value, | ||
trader: psmTrader, | ||
fee: Number(wantMintedFeeVal) / 100, // fee has to be between 0 and 1 | ||
anchor, | ||
}); | ||
}); | ||
|
||
test.serial('swap out of IST', async t => { | ||
const { | ||
newUser: { name }, | ||
anchor, | ||
fromIst, | ||
govParams: { giveMintedFeeVal }, | ||
} = psmTestSpecs; | ||
|
||
const psmTrader = await getUser(name); | ||
|
||
const [metricsBefore, balancesBefore] = await Promise.all([ | ||
getPsmMetrics(anchor), | ||
getBalances([psmTrader]), | ||
]); | ||
|
||
t.log('METRICS', metricsBefore); | ||
t.log('BALANCES', balancesBefore); | ||
|
||
await agopsPsm(psmTrader, [ | ||
'swap', | ||
'--pair', | ||
process.env.PSM_PAIR, | ||
'--giveMinted', | ||
fromIst.value, | ||
'--feePct', | ||
giveMintedFeeVal, | ||
]); | ||
await waitForBlock(5); | ||
|
||
await checkSwapSucceeded(t, metricsBefore, balancesBefore, { | ||
giveMinted: fromIst.value, | ||
trader: psmTrader, | ||
fee: Number(giveMintedFeeVal) / 100, // fee has to be between 0 and 1 | ||
anchor, | ||
}); | ||
}); | ||
|
||
test.serial('mint limit is adhered', async t => { | ||
const { | ||
otherUser: { | ||
fund: { denom, value }, | ||
name, | ||
}, | ||
govParams, | ||
anchor, | ||
} = psmTestSpecs; | ||
|
||
// Fund other user | ||
const otherAddr = await getUser(name); | ||
await bankSend(otherAddr, `${value}${denom}`); | ||
|
||
// Replace when https://github.com/Agoric/agoric-sdk/pull/10171 is in | ||
await waitForBlock(3); | ||
|
||
const [metricsBefore, balancesBefore] = await Promise.all([ | ||
getPsmMetrics(anchor), | ||
getBalances([otherAddr]), | ||
]); | ||
|
||
t.log('METRICS', metricsBefore); | ||
t.log('BALANCES', balancesBefore); | ||
|
||
const { maxMintableValue, wantFeeValue } = await maxMintBelowLimit(anchor); | ||
const maxMintFeesAccounted = Math.floor( | ||
maxMintableValue * (1 - wantFeeValue), | ||
); | ||
t.log({ maxMintableValue, wantFeeValue, maxMintFeesAccounted }); | ||
|
||
// Send a swap, should fail because mint limit is exceeded | ||
await agopsPsm(otherAddr, [ | ||
'swap', | ||
'--pair', | ||
process.env.PSM_PAIR, | ||
'--wantMinted', | ||
maxMintFeesAccounted / 1000000 + 2, // Make sure we exceed the limit | ||
'--feePct', | ||
govParams.wantMintedFeeVal, | ||
]); | ||
await waitForBlock(5); | ||
|
||
// Now check if failed with correct error message | ||
await checkSwapExceedMintLimit(t, otherAddr, metricsBefore); | ||
|
||
// Send another swap offer, this time should succeed | ||
await agopsPsm(otherAddr, [ | ||
'swap', | ||
'--pair', | ||
process.env.PSM_PAIR, | ||
'--wantMinted', | ||
maxMintFeesAccounted / 1000000, | ||
'--feePct', | ||
govParams.wantMintedFeeVal, | ||
]); | ||
await waitForBlock(5); | ||
|
||
// Make sure swap succeeded | ||
await checkSwapSucceeded(t, metricsBefore, balancesBefore, { | ||
wantMinted: maxMintFeesAccounted / 1000000, | ||
trader: otherAddr, | ||
fee: Number(govParams.wantMintedFeeVal) / 100, // fee has to be between 0 and 1 | ||
anchor, | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.