-
Notifications
You must be signed in to change notification settings - Fork 254
fix(portfolio-contract)!: limit outbound CCTP to >= 1USDC #12184
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -171,6 +171,13 @@ export const CCTPfromEVM = { | |
| } as const satisfies TransportDetail<'CCTP', AxelarChain, 'agoric', EVMContext>; | ||
| harden(CCTPfromEVM); | ||
|
|
||
| /** | ||
| * Noble CCTP relayer policy is to not relay very small amounts. | ||
| * | ||
| * XXX could be configurable for test networks | ||
| */ | ||
| const CCTP_OUTBOUND_THRESHOLD = 1_000_000n; | ||
|
|
||
| export const CCTP = { | ||
| how: 'CCTP', | ||
| connections: keys(AxelarChain).map((dest: AxelarChain) => ({ | ||
|
|
@@ -182,6 +189,8 @@ export const CCTP = { | |
| const denomAmount: DenomAmount = { denom: 'uusdc', value: amount.value }; | ||
| const { chainId, remoteAddress } = dest; | ||
| traceTransfer('transfer', denomAmount, 'to', remoteAddress); | ||
| amount.value >= CCTP_OUTBOUND_THRESHOLD || | ||
| Fail`too small to relay: ${amount} below ${CCTP_OUTBOUND_THRESHOLD}`; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it be
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any particular reason? Oh... I guess it should be q(amount) |
||
| const destinationAddress: AccountId = `${chainId}:${remoteAddress}`; | ||
| const { ica } = src; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -640,7 +640,7 @@ test( | |||||
| ); | ||||||
|
|
||||||
| test('open portfolio with Aave position', async t => { | ||||||
| const amount = AmountMath.make(USDC, 300n); | ||||||
| const amount = AmountMath.make(USDC, 2_000_000n); | ||||||
| const feeAcct = AmountMath.make(BLD, 50n); | ||||||
| const detail = { evmGas: 50n }; | ||||||
| const feeCall = AmountMath.make(BLD, 100n); | ||||||
|
|
@@ -678,7 +678,7 @@ test('open portfolio with Aave position', async t => { | |||||
| { _method: 'transfer', address: { chainId: 'axelar-6' } }, | ||||||
| { | ||||||
| _method: 'localTransfer', | ||||||
| amounts: { Deposit: { value: 300n } }, | ||||||
| amounts: { Deposit: { value: 2_000_000n } }, | ||||||
| }, | ||||||
| { _method: 'transfer', address: { chainId: 'noble-5' } }, | ||||||
| { _method: 'depositForBurn' }, | ||||||
|
|
@@ -707,7 +707,7 @@ test.skip('reject missing fee before committing anything', t => { | |||||
|
|
||||||
| test('open portfolio with Compound position', async t => { | ||||||
| const { give, steps } = await makePortfolioSteps( | ||||||
| { Compound: make(USDC, 300n) }, | ||||||
| { Compound: make(USDC, 2_000_000n) }, | ||||||
| { fees: { Compound: { Account: make(BLD, 300n), Call: make(BLD, 100n) } } }, | ||||||
| ); | ||||||
| const { orch, tapPK, ctx, offer, storage, txResolver } = mocks({}, give); | ||||||
|
|
@@ -730,7 +730,7 @@ test('open portfolio with Compound position', async t => { | |||||
| { _method: 'transfer', address: { chainId: 'noble-5' } }, | ||||||
| { _method: 'send' }, | ||||||
| { _method: 'transfer', address: { chainId: 'axelar-6' } }, | ||||||
| { _method: 'localTransfer', amounts: { Deposit: { value: 300n } } }, | ||||||
| { _method: 'localTransfer', amounts: { Deposit: { value: 2_000_000n } } }, | ||||||
| { _method: 'transfer', address: { chainId: 'noble-5' } }, | ||||||
| { _method: 'depositForBurn' }, | ||||||
| { _method: 'send' }, | ||||||
|
|
@@ -941,7 +941,7 @@ test.skip('rebalance handles stepFlow failure correctly', async t => { | |||||
| }); | ||||||
|
|
||||||
| test('claim rewards on Aave position', async t => { | ||||||
| const amount = AmountMath.make(USDC, 300n); | ||||||
| const amount = AmountMath.make(USDC, 2_000_000n); | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider using
Suggested change
Even better you could inline the |
||||||
| const emptyAmount = AmountMath.make(USDC, 0n); | ||||||
| const feeCall = AmountMath.make(BLD, 100n); | ||||||
| const { orch, tapPK, ctx, offer, storage, txResolver } = mocks( | ||||||
|
|
@@ -999,7 +999,7 @@ test('claim rewards on Aave position', async t => { | |||||
| }); | ||||||
|
|
||||||
| test('open portfolio with Beefy position', async t => { | ||||||
| const amount = AmountMath.make(USDC, 300n); | ||||||
| const amount = AmountMath.make(USDC, 2_000_000n); | ||||||
| const feeAcct = AmountMath.make(BLD, 50n); | ||||||
| const detail = { evmGas: 50n }; | ||||||
| const feeCall = AmountMath.make(BLD, 100n); | ||||||
|
|
@@ -1041,7 +1041,7 @@ test('open portfolio with Beefy position', async t => { | |||||
| { _method: 'transfer', address: { chainId: 'axelar-6' } }, | ||||||
| { | ||||||
| _method: 'localTransfer', | ||||||
| amounts: { Deposit: { value: 300n } }, | ||||||
| amounts: { Deposit: { value: 2_000_000n } }, | ||||||
| }, | ||||||
| { _method: 'transfer', address: { chainId: 'noble-5' } }, | ||||||
| { _method: 'depositForBurn' }, | ||||||
|
|
@@ -1062,7 +1062,7 @@ test('open portfolio with Beefy position', async t => { | |||||
| }); | ||||||
|
|
||||||
| test('wayFromSrcToDesc handles +agoric -> @agoric', t => { | ||||||
| const amount = AmountMath.make(USDC, 300n); | ||||||
| const amount = AmountMath.make(USDC, 2_000_000n); | ||||||
| const actual = wayFromSrcToDesc({ src: '+agoric', dest: '@agoric', amount }); | ||||||
| t.deepEqual(actual, { how: 'send' }); | ||||||
| }); | ||||||
|
|
@@ -1071,7 +1071,7 @@ test('Engine can move deposits +agoric -> @agoric', async t => { | |||||
| const { orch, ctx, offer, storage } = mocks({}, {}); | ||||||
| const { log } = offer; | ||||||
|
|
||||||
| const amount = AmountMath.make(USDC, 300n); | ||||||
| const amount = AmountMath.make(USDC, 2_000_000n); | ||||||
| const kit = await ctx.makePortfolioKit(); | ||||||
|
|
||||||
| await rebalance( | ||||||
|
|
@@ -1099,7 +1099,7 @@ test('client can move to deposit LCA', async t => { | |||||
| const { orch, ctx, offer, storage } = mocks({}, {}); | ||||||
| const { log } = offer; | ||||||
|
|
||||||
| const amount = AmountMath.make(USDC, 300n); | ||||||
| const amount = AmountMath.make(USDC, 2_000_000n); | ||||||
| const kit = await ctx.makePortfolioKit(); | ||||||
|
|
||||||
| await rebalance( | ||||||
|
|
@@ -1207,7 +1207,7 @@ test('handle failure in provideCosmosAccount makeAccount', async t => { | |||||
| test('handle failure in provideEVMAccount sendMakeAccountCall', async t => { | ||||||
| const unlucky = make(BLD, 13n); | ||||||
| const { give, steps } = await makePortfolioSteps( | ||||||
| { Compound: make(USDC, 300n) }, | ||||||
| { Compound: make(USDC, 2_000_000n) }, | ||||||
| { | ||||||
| fees: { Compound: { Account: unlucky, Call: make(BLD, 100n) } }, | ||||||
| evm: 'Arbitrum', | ||||||
|
|
@@ -1256,7 +1256,7 @@ test('handle failure in provideEVMAccount sendMakeAccountCall', async t => { | |||||
|
|
||||||
| // Recovery attempt - avoid the unlucky 13n fee using same portfolio | ||||||
| const { give: giveGood, steps: stepsGood } = await makePortfolioSteps( | ||||||
| { Compound: make(USDC, 300n) }, | ||||||
| { Compound: make(USDC, 2_000_000n) }, | ||||||
| { fees: { Compound: { Account: make(BLD, 300n), Call: make(BLD, 100n) } } }, | ||||||
| ); | ||||||
| const seat2 = makeMockSeat(giveGood, undefined, log); | ||||||
|
|
@@ -1322,7 +1322,7 @@ test('withdraw in coordination with planner', async t => { | |||||
| } | ||||||
|
|
||||||
| const webUiDone = (async () => { | ||||||
| const Cash = make(USDC, 300n); | ||||||
| const Cash = make(USDC, 2_000_000n); | ||||||
| const wSeat = makeMockSeat({}, { Cash }, offer.log); | ||||||
| await executePlan(orch, ctx, wSeat, {}, kit, { | ||||||
| type: 'withdraw', | ||||||
|
|
@@ -1373,7 +1373,7 @@ test('withdraw in coordination with planner', async t => { | |||||
| }, | ||||||
| { _method: 'send', _cap: 'agoric11014' }, | ||||||
| { _method: 'transfer' }, // depositForBurn | ||||||
| { _method: 'withdrawToSeat', amounts: { Cash: { value: 300n } } }, | ||||||
| { _method: 'withdrawToSeat', amounts: { Cash: { value: 2_000_000n } } }, | ||||||
| { _method: 'exit' }, | ||||||
| ]); | ||||||
| t.snapshot(log, 'call log'); // see snapshot for remaining arg details | ||||||
|
|
@@ -1488,17 +1488,17 @@ test('simple rebalance in coordination with planner', async t => { | |||||
|
|
||||||
| // Planner provides steps to move from USDN to mixed allocation | ||||||
| const steps: MovementDesc[] = [ | ||||||
| { src: 'USDN', dest: '@noble', amount: make(USDC, 5000n) }, | ||||||
| { src: 'USDN', dest: '@noble', amount: make(USDC, 5_000_000n) }, | ||||||
| { | ||||||
| src: '@noble', | ||||||
| dest: '@Arbitrum', | ||||||
| amount: make(USDC, 5000n), | ||||||
| amount: make(USDC, 5_000_000n), | ||||||
| fee: make(BLD, 100n), | ||||||
| }, | ||||||
| { | ||||||
| src: '@Arbitrum', | ||||||
| dest: 'Aave_Arbitrum', | ||||||
| amount: make(USDC, 5000n), | ||||||
| amount: make(USDC, 5_000_000n), | ||||||
| fee: make(BLD, 50n), | ||||||
| }, | ||||||
| ]; | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add a test for threshold enforcement.
A test that uses values less than 1 USDC.