diff --git a/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md b/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md index 8c2eda981f40..68ea14d4de85 100644 --- a/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md +++ b/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.md @@ -17,7 +17,9 @@ Generated by [AVA](https://avajs.dev). { chainPolicies: { Arbitrum: { - attenuatedCttpBridgeAddress: '0xe298b93ffB5eA1FB628e0C0D55A43aeaC268e347', + attenuatedCttpBridgeAddresses: [ + '0xe298b93ffB5eA1FB628e0C0D55A43aeaC268e347', + ], cctpTokenMessengerAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A', chainId: 42161, confirmations: 2, @@ -28,7 +30,9 @@ Generated by [AVA](https://avajs.dev). }, }, Base: { - attenuatedCttpBridgeAddress: '0xB6615B2662b35fc3533F8479002e62D0523341De', + attenuatedCttpBridgeAddresses: [ + '0xB6615B2662b35fc3533F8479002e62D0523341De', + ], cctpTokenMessengerAddress: '0x1682Ae6375C4E4A97e4B583BC394c861A46D8962', chainId: 8453, confirmations: 2, @@ -39,7 +43,9 @@ Generated by [AVA](https://avajs.dev). }, }, Ethereum: { - attenuatedCttpBridgeAddress: '0xBC8552339dA68EB65C8b88B414B5854E0E366cFc', + attenuatedCttpBridgeAddresses: [ + '0xBC8552339dA68EB65C8b88B414B5854E0E366cFc', + ], cctpTokenMessengerAddress: '0xBd3fa81B58Ba92a82136038B25aDec7066af3155', chainId: 1, confirmations: 2, @@ -50,7 +56,9 @@ Generated by [AVA](https://avajs.dev). }, }, Optimism: { - attenuatedCttpBridgeAddress: '0x48C5417ED570928eC85D5e3AD4e7E0EeD7dB1E2A', + attenuatedCttpBridgeAddresses: [ + '0x48C5417ED570928eC85D5e3AD4e7E0EeD7dB1E2A', + ], cctpTokenMessengerAddress: '0x2B4069517957735bE00ceE0fadAE88a26365528f', chainId: 10, confirmations: 2, @@ -61,7 +69,9 @@ Generated by [AVA](https://avajs.dev). }, }, Polygon: { - attenuatedCttpBridgeAddress: '0x32cb9574650AFF312c80edc4B4343Ff5500767cA', + attenuatedCttpBridgeAddresses: [ + '0x32cb9574650AFF312c80edc4B4343Ff5500767cA', + ], cctpTokenMessengerAddress: '0x9daF8c91AEFAE50b9c0E69629D3F6Ca40cA3B3FE', chainId: 137, confirmations: 2, diff --git a/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.snap b/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.snap index 1bb5a5dc63b7..852bea26923c 100644 Binary files a/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.snap and b/packages/boot/test/fast-usdc/snapshots/fast-usdc.test.ts.snap differ diff --git a/packages/fast-usdc/src/type-guards.js b/packages/fast-usdc/src/type-guards.js index 778e4c84a6a4..5ece98c4ac94 100644 --- a/packages/fast-usdc/src/type-guards.js +++ b/packages/fast-usdc/src/type-guards.js @@ -122,7 +122,11 @@ harden(PoolMetricsShape); /** @type {TypedPattern} */ export const ChainPolicyShape = { - attenuatedCttpBridgeAddress: EvmHashShape, + attenuatedCttpBridgeAddresses: M.splitArray( + [EvmHashShape], + undefined, + M.arrayOf(EvmHashShape), + ), cctpTokenMessengerAddress: EvmHashShape, confirmations: M.number(), chainId: M.number(), diff --git a/packages/fast-usdc/src/types.ts b/packages/fast-usdc/src/types.ts index b169ea48a17b..bc9bf5cd4ca5 100644 --- a/packages/fast-usdc/src/types.ts +++ b/packages/fast-usdc/src/types.ts @@ -82,7 +82,7 @@ export interface PoolMetrics extends PoolStats { export interface ChainPolicy { /** `msg.sender` of DepositAndBurn to TokenMessenger must be an attenuated wrapper contract that does not contain `replaceDepositForBurn` */ - attenuatedCttpBridgeAddress: EvmHash; + attenuatedCttpBridgeAddresses: EvmHash[]; /** @see {@link https://developers.circle.com/stablecoins/evm-smart-contracts} */ cctpTokenMessengerAddress: EvmHash; /** e.g., `1` for ETH mainnet 42161 for Arbitrum One. @see {@link https://chainlist.org/} */ diff --git a/packages/fast-usdc/src/utils/chain-policies.js b/packages/fast-usdc/src/utils/chain-policies.js index 192e7cae4aed..cc52dc045f4e 100644 --- a/packages/fast-usdc/src/utils/chain-policies.js +++ b/packages/fast-usdc/src/utils/chain-policies.js @@ -4,7 +4,9 @@ export const ChainPolicies = /** @type {const} */ ({ MAINNET: { Arbitrum: { - attenuatedCttpBridgeAddress: '0xe298b93ffB5eA1FB628e0C0D55A43aeaC268e347', + attenuatedCttpBridgeAddresses: [ + '0xe298b93ffB5eA1FB628e0C0D55A43aeaC268e347', + ], cctpTokenMessengerAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A', chainId: 42161, // TODO confirm confirmations and rateLimits @@ -16,7 +18,9 @@ export const ChainPolicies = /** @type {const} */ ({ }, }, Base: { - attenuatedCttpBridgeAddress: '0xB6615B2662b35fc3533F8479002e62D0523341De', + attenuatedCttpBridgeAddresses: [ + '0xB6615B2662b35fc3533F8479002e62D0523341De', + ], cctpTokenMessengerAddress: '0x1682Ae6375C4E4A97e4B583BC394c861A46D8962', chainId: 8453, // TODO confirm confirmations and rateLimits @@ -28,7 +32,9 @@ export const ChainPolicies = /** @type {const} */ ({ }, }, Ethereum: { - attenuatedCttpBridgeAddress: '0xBC8552339dA68EB65C8b88B414B5854E0E366cFc', + attenuatedCttpBridgeAddresses: [ + '0xBC8552339dA68EB65C8b88B414B5854E0E366cFc', + ], cctpTokenMessengerAddress: '0xBd3fa81B58Ba92a82136038B25aDec7066af3155', chainId: 1, // TODO confirm confirmations and rateLimits @@ -40,7 +46,9 @@ export const ChainPolicies = /** @type {const} */ ({ }, }, Optimism: { - attenuatedCttpBridgeAddress: '0x48C5417ED570928eC85D5e3AD4e7E0EeD7dB1E2A', + attenuatedCttpBridgeAddresses: [ + '0x48C5417ED570928eC85D5e3AD4e7E0EeD7dB1E2A', + ], cctpTokenMessengerAddress: '0x2B4069517957735bE00ceE0fadAE88a26365528f', chainId: 10, // TODO confirm confirmations and rateLimits @@ -52,7 +60,9 @@ export const ChainPolicies = /** @type {const} */ ({ }, }, Polygon: { - attenuatedCttpBridgeAddress: '0x32cb9574650AFF312c80edc4B4343Ff5500767cA', + attenuatedCttpBridgeAddresses: [ + '0x32cb9574650AFF312c80edc4B4343Ff5500767cA', + ], cctpTokenMessengerAddress: '0x9daF8c91AEFAE50b9c0E69629D3F6Ca40cA3B3FE', chainId: 137, // TODO confirm confirmations and rateLimits @@ -67,7 +77,7 @@ export const ChainPolicies = /** @type {const} */ ({ TESTNET: { // Arbitrum Sepolia Arbitrum: { - attenuatedCttpBridgeAddress: '0xTODO', + attenuatedCttpBridgeAddresses: ['0xTODO'], cctpTokenMessengerAddress: '0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5', chainId: 421614, confirmations: 2, @@ -79,7 +89,7 @@ export const ChainPolicies = /** @type {const} */ ({ }, // Base Sepolia Base: { - attenuatedCttpBridgeAddress: '0xTODO', + attenuatedCttpBridgeAddresses: ['0xTODO'], cctpTokenMessengerAddress: '0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5', chainId: 84532, confirmations: 2, @@ -91,7 +101,7 @@ export const ChainPolicies = /** @type {const} */ ({ }, // Ethereum Sepolia Ethereum: { - attenuatedCttpBridgeAddress: '0xTODO', + attenuatedCttpBridgeAddresses: ['0xTODO'], cctpTokenMessengerAddress: '0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5', chainId: 11155111, confirmations: 2, @@ -103,7 +113,7 @@ export const ChainPolicies = /** @type {const} */ ({ }, // OP Sepolia Optimism: { - attenuatedCttpBridgeAddress: '0xTODO', + attenuatedCttpBridgeAddresses: ['0xTODO'], cctpTokenMessengerAddress: '0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5', chainId: 11155420, confirmations: 2, @@ -115,7 +125,7 @@ export const ChainPolicies = /** @type {const} */ ({ }, // Polygon PoS Amoy Polygon: { - attenuatedCttpBridgeAddress: '0xTODO', + attenuatedCttpBridgeAddresses: ['0xTODO'], cctpTokenMessengerAddress: '0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5', chainId: 80002, confirmations: 2, diff --git a/packages/fast-usdc/test/type-guards.test.ts b/packages/fast-usdc/test/type-guards.test.ts index 6838092165ea..4528d3caa7c4 100644 --- a/packages/fast-usdc/test/type-guards.test.ts +++ b/packages/fast-usdc/test/type-guards.test.ts @@ -2,10 +2,15 @@ import { test } from '@agoric/zoe/tools/prepare-test-env-ava.js'; import { M, mustMatch } from '@endo/patterns'; import { TxStatus, PendingTxStatus } from '../src/constants.js'; -import { CctpTxEvidenceShape, PendingTxShape } from '../src/type-guards.js'; -import type { CctpTxEvidence } from '../src/types.js'; +import { + CctpTxEvidenceShape, + ChainPolicyShape, + PendingTxShape, +} from '../src/type-guards.js'; +import type { CctpTxEvidence, ChainPolicy } from '../src/types.js'; import { MockCctpTxEvidences } from './fixtures.js'; +import { ChainPolicies } from '../src/utils/chain-policies.js'; test('CctpTxEvidenceShape', t => { const specimen: CctpTxEvidence = harden( @@ -37,3 +42,46 @@ test('PendingTxShape', t => { ), ); }); + +test('ChainPolicyShape', t => { + const policy: ChainPolicy = harden({ + attenuatedCttpBridgeAddresses: [ + '0xe298b93ffB5eA1FB628e0C0D55A43aeaC268e347', + ], + rateLimits: { + blockWindow: 20_000_000_000n, + blockWindowSize: 10, + tx: 10_000_000_000n, + }, + cctpTokenMessengerAddress: '0x19330d10D9Cc8751218eaf51E8885D058642E08A', + chainId: 42161, + confirmations: 2, + }); + t.notThrows(() => mustMatch(policy, ChainPolicyShape)); + + const a = policy.attenuatedCttpBridgeAddresses[0]; + const twoAddrs = harden({ + ...policy, + attenuatedCttpBridgeAddresses: [a, a], + }); + t.notThrows(() => mustMatch(twoAddrs, ChainPolicyShape)); + + const threeAddrs = harden({ + ...policy, + attenuatedCttpBridgeAddresses: [a, a, a], + }); + t.notThrows(() => mustMatch(threeAddrs, ChainPolicyShape)); + + t.notThrows(() => + mustMatch( + harden(Object.values(ChainPolicies.MAINNET)), + M.arrayOf(ChainPolicyShape), + ), + ); + + const noAddrs = harden({ + ...policy, + attenuatedCttpBridgeAddresses: [], + }); + t.throws(() => mustMatch(noAddrs, ChainPolicyShape)); +});