diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index b9bcd0555a..8e517673fd 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -32,7 +32,7 @@ jobs: { "name": "functions", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "keystone", "setup": { "run-coverage": true, "min-coverage": 72.8, "run-gas-snapshot": false, "run-forge-fmt": false }}, { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 61.0, "run-gas-snapshot": true, "run-forge-fmt": false }}, - { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 46.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 44.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "llo-feeds", "setup": { "run-coverage": true, "min-coverage": 49.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "operatorforwarder", "setup": { "run-coverage": true, "min-coverage": 55.7, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "shared", "setup": { "run-coverage": true, "extra-coverage-params": "--no-match-path='*CallWithExactGas*'", "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 3042fa4ce4..06ce02dd07 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -19,25 +19,23 @@ AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 19016) AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17546) AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30393) AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32407) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28842) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244024) -BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24166) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27609) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241912) -BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17851) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28805) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56253) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112391) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28842) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244050) -BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24168) -BurnWithFromMintTokenPool_releaseOrMint:test_Setup_Success() (gas: 24547) -BurnWithFromMintTokenPool_releaseOrMint:test_releaseOrMint_NegativeMintAmount_reverts() (gas: 93840) -BurnWithFromMintTokenPool_releaseOrMint:test_releaseOrMint_Success() (gas: 93423) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2058831) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27346) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54856) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244410) +BurnFromMintTokenPool_lockOrBurn:test_setup_Success() (gas: 24167) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27486) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54856) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 242315) +BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17830) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 27309) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 54618) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 109405) +BurnMintWithLockReleaseFlagTokenPool_lockOrBurn:test_LockOrBurn_CorrectReturnData_Success() (gas: 242495) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27346) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 54856) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244454) +BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24180) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2060218) CCIPHome__validateConfig:test__validateConfigLessTransmittersThanSigners_Success() (gas: 334693) CCIPHome__validateConfig:test__validateConfigSmallerFChain_Success() (gas: 466117) CCIPHome__validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 289739) @@ -112,30 +110,30 @@ CommitStore_verify:test_Blessed_Success() (gas: 96581) CommitStore_verify:test_NotBlessed_Success() (gas: 61473) CommitStore_verify:test_Paused_Revert() (gas: 18568) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36848) -DefensiveExampleTest:test_HappyPath_Success() (gas: 200200) -DefensiveExampleTest:test_Recovery() (gas: 424476) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1141917) +DefensiveExampleTest:test_HappyPath_Success() (gas: 200267) +DefensiveExampleTest:test_Recovery() (gas: 424613) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1138593) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38322) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 104438) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 83526) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 101428) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 80487) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37365) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95013) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91915) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 37841) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 87189) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 381594) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 140568) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 798833) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 178400) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29681) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 67146) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43605) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 208068) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 219365) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 84113) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 369720) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 137592) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 766486) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 171941) +EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29717) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 67360) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43677) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 202313) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 213452) EVM2EVMOffRamp__report:test_Report_Success() (gas: 127774) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237406) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246039) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329283) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 310166) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 230875) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 239552) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 323274) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 304201) EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17048) EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153120) EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5212732) @@ -143,7 +141,7 @@ EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 143845) EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21507) EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36936) EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 52324) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473387) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 463753) EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 48346) EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 153019) EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103946) @@ -154,25 +152,25 @@ EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 16011 EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 175497) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 237901) EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115048) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 406606) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 400597) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54774) EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132556) EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52786) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564471) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494719) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 556453) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 486701) EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35887) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546333) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 538315) EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 65298) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 124107) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 144365) EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 394187) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18685) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 275257) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 269248) EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18815) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 223182) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 216651) EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48391) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47823) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 311554) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 305545) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70839) EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 232136) EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 281170) @@ -186,13 +184,13 @@ EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 188280) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27574) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 46457) EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27948) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 531330) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 344463) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 523312) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 338454) EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 189760) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2195128) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362054) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2192118) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 356045) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 145457) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 365283) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 359274) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 450711) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 192223) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 155387) @@ -206,36 +204,36 @@ EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert( EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197985) EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5056698) EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 36063) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99010) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114925) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114967) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130991) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 139431) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 130607) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99022) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114937) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114979) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 131003) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 139443) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 130619) EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38647) EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38830) EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25726) EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25545) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 84266) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 84273) EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36847) EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29327) EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107850) EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22823) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 226568) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 227322) EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53432) EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25757) EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 57722) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 182247) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 180718) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 133236) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3573653) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 133270) +EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3943537) EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30472) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43480) EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110111) EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 316020) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 113033) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 113067) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72824) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 714726) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 719887) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 148808) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 192679) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 123243) @@ -264,15 +262,15 @@ EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21353) EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28382) EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38899) EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29674) -EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32756) -EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 135247) -EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143660) -EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29196) -EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127718) -EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133580) -EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146947) -EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141522) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 298719) +EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32773) +EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 135254) +EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143667) +EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29213) +EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127659) +EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133532) +EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146954) +EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141529) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 298706) EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15378) EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42524) EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21426) @@ -281,10 +279,10 @@ EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 1 EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16497) EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 14036) EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61872) -EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 470835) +EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 470886) EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57370) EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14779) -EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 85200) +EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 85222) EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60868) EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 174097) EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 193503) @@ -293,10 +291,10 @@ EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidD EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14427) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 85487) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17468) -EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83617) +EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83639) EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15353) -EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272851) -EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53566) +EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272970) +EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53627) EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12875) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96907) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49775) @@ -360,32 +358,32 @@ FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Succes FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27781) FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40372) FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29499) -FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18354) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82824) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53482) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239286) -FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22593) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29879) -FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100330) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 142496) -FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21211) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 113826) -FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22729) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63709) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1973907) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1973865) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1953984) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1973639) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1973843) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1973655) +FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18414) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82992) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 53530) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 239454) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22617) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29903) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100366) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 142856) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21223) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 114090) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22765) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63829) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1913624) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1913582) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1893701) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1913356) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1913560) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1913372) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64610) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64490) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58894) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1973352) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1913069) FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61764) FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116495) FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14037) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1972029) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1911746) FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43675) FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23514) FeeQuoter_onReport:test_onReport_Success() (gas: 80116) @@ -396,15 +394,15 @@ FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() ( FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18154) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18513) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18636) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44725) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44860) FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19914) FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20333) FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17904) -FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 122753) -FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42054) +FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 122889) +FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42122) FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28578) FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29949) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76189) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76465) FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28176) FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26047) FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19523) @@ -424,59 +422,31 @@ FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() ( FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10839) FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6731) FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6511) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209248) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135879) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107090) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144586) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214817) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423641) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268928) -HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111484) -HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39362) -HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 33189) -HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12669) -HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13329) -HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160900) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 255982) -HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165921) -HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 154242) -HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 463740) -HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209230) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135880) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107135) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144607) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214795) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423619) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268910) -HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111528) -HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160845) -HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165904) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10989) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18028) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3051552) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3047988) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) -LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 10196) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60187) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2836138) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30062) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79943) -LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59620) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2832618) +HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 176771) +HybridLockReleaseUSDCTokenPool_TransferLiquidity:test_transferLiquidity_Success() (gas: 166828) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_PrimaryMechanism_Success() (gas: 135764) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_WhileMigrationPause_Revert() (gas: 109696) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_Success() (gas: 146859) +HybridLockReleaseUSDCTokenPool_lockOrBurn:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 208941) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 213084) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 109606) +HybridLockReleaseUSDCTokenPool_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 265786) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3129432) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29734) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 80502) +LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59205) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3125846) LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72743) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56352) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225548) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11011) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18094) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 74080) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 54717) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 223184) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10893) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18072) LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10196) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83231) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55953) -LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60187) -LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11054) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35060) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83270) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 56019) +LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60122) +LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11397) MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5478) MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3585) MerkleMultiProofTest:test_MerkleRoot256() (gas: 394891) @@ -487,8 +457,8 @@ MockRouterTest:test_ccipSendWithEVMExtraArgsV2_Success() (gas: 132614) MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34037) MockRouterTest:test_ccipSendWithInvalidEVMExtraArgs_Revert() (gas: 106684) MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60886) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126640) -MockRouterTest:test_ccipSendWithLinkFeeTokenButInsufficientAllowance_Revert() (gas: 63478) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126696) +MockRouterTest:test_ccipSendWithLinkFeeTokenButInsufficientAllowance_Revert() (gas: 63500) MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44048) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 133528) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 315630) @@ -568,8 +538,8 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24234) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61275) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39933) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33049) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233732) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1518567) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233865) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1512594) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37934) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23706) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38778) @@ -627,13 +597,13 @@ OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13463) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72746) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177991) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335638) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 278904) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169320) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189033) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 157144) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 554256) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 178112) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335759) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 279025) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169394) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189154) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 157181) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 546430) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10622) OffRamp_ccipReceive:test_Reverts() (gas: 15407) OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92905) @@ -664,97 +634,97 @@ OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161468) OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101189) OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101227) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) -OffRamp_execute:test_LargeBatch_Success() (gas: 3426335) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372990) -OffRamp_execute:test_MultipleReports_Success() (gas: 300979) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7083611) -OffRamp_execute:test_NoConfig_Revert() (gas: 6308086) -OffRamp_execute:test_NonArray_Revert() (gas: 27562) -OffRamp_execute:test_SingleReport_Success() (gas: 176354) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148372) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7086360) +OffRamp_execute:test_LargeBatch_Success() (gas: 3427645) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 373111) +OffRamp_execute:test_MultipleReports_Success() (gas: 301100) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7083648) +OffRamp_execute:test_NoConfig_Revert() (gas: 6308123) +OffRamp_execute:test_NonArray_Revert() (gas: 27599) +OffRamp_execute:test_SingleReport_Success() (gas: 176391) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148409) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7086397) OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18533) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 244079) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 238070) OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20781) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 205116) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 198585) OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49306) OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48750) OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218028) OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85296) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 274196) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 268187) OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91724) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28282) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22084) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 481794) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48394) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33981) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28458) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188096) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198552) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40763) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 413245) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 249800) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193614) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 213648) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 249550) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142163) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409313) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58315) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73890) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 583427) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 532141) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33739) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 549786) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 549800) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 460521) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135944) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165649) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28319) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22074) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 472256) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48431) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34018) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28495) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188133) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198626) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40800) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 413282) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 249874) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193688) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 213722) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 249587) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142200) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 403400) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58352) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73930) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 575505) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 524219) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33823) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 541960) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 541974) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 452599) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136018) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165723) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3885554) OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120606) OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89288) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81016) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74027) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173167) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214124) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27085) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 164696) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27622) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55193) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 498549) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 316061) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2245222) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165525) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227169) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227709) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781365) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347346) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81352) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74113) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173204) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214198) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27122) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165422) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27659) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55236) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 498623) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 316276) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2242292) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165599) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227243) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227783) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781795) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347514) OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37656) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 104404) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 82842) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 101388) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 79803) OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36752) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94382) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 91284) OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 37241) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86516) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 162381) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 83440) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 155850) OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 23903) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 62751) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 79790) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 174468) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 176380) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 187679) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 62773) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 78303) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 168497) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 170409) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 181670) OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11291) OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13906) OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46378) OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24420) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 219377) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 227999) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 295396) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 277896) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 396282) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 18018) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67797) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325198) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 212846) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 221512) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 289387) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 271931) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 398904) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 18030) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67893) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325457) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65878) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13631) OnRamp_constructor:test_Constructor_EnableAllowList_ForwardFromRouter_Reverts() (gas: 2673564) @@ -763,15 +733,15 @@ OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Rever OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98224) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93247) OnRamp_constructor:test_Constructor_Success() (gas: 2753286) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115367) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146168) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145765) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143926) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145962) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145360) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140701) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115379) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146180) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145777) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143938) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145974) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145372) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140713) OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38554) -OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143051) +OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143063) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36596) OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36527) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18291) @@ -779,13 +749,13 @@ OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38431) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23640) OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186528) OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212912) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 146994) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161099) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3615170) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 147028) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 161133) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3984961) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24010) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75866) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38599) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 280252) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281479) OnRamp_getFee:test_EmptyMessage_Success() (gas: 98597) OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 65467) OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87012) @@ -800,12 +770,12 @@ OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigInvalidConfig_Revert( OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (gas: 16850) OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13265) OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56347) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97302) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 155829) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97341) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 155846) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20310) PingPong_plumbing:test_Pausing_Success() (gas: 17810) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 167051) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 186469) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 167068) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 186486) RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateOffchainPublicKey_reverts() (gas: 18822) RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicatePeerId_reverts() (gas: 18682) RMNHome__validateStaticAndDynamicConfig:test_validateStaticAndDynamicConfig_DuplicateSourceChain_reverts() (gas: 20371) @@ -931,21 +901,21 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89366) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10662612) Router_applyRampUpdates:test_OnRampDisable() (gas: 56007) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12356) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 115079) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 202910) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 115091) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 203469) Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 127448) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215281) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 69000) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215829) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 69017) Router_ccipSend:test_InvalidMsgValue() (gas: 32155) Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 71657) Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 175345) Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 58759) Router_ccipSend:test_NativeFeeToken_Success() (gas: 173861) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 243729) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 243736) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24854) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44811) Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 176149) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 246683) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 246695) Router_constructor:test_Constructor_Success() (gas: 13128) Router_getArmProxy:test_getArmProxy() (gas: 10573) Router_getFee:test_GetFeeSupportedChain_Success() (gas: 49153) @@ -955,7 +925,7 @@ Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11334) Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20267) Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11171) Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 358049) -Router_recoverTokens:test_RecoverTokens_Success() (gas: 52480) +Router_recoverTokens:test_RecoverTokens_Success() (gas: 52508) Router_routeMessage:test_AutoExec_Success() (gas: 42816) Router_routeMessage:test_ExecutionEvent_Success() (gas: 158520) Router_routeMessage:test_ManualExec_Success() (gas: 35546) @@ -963,7 +933,7 @@ Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25224) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44799) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10998) SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55660) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 428138) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 428230) SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20181) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51163) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 44004) @@ -987,58 +957,102 @@ TokenAdminRegistry_setPool:test_setPool_Success() (gas: 36135) TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30842) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18103) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49438) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5586499) -TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5618769) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 5793246) -TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3070731) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6440241) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 6640374) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 1979943) -TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12113) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23476) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177848) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2732579) +TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12059) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23512) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177934) TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23764) -TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8375) +TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8353) TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24867) -TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271569) -TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 542359) -TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18449) -TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11469) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 479160) -TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157422) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70484) -TokenPool_constructor:test_immutableFields_Success() (gas: 20586) -TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274181) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277296) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 290028) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 350050) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277036) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 254065) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 305106) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17187) -TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15227) -TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15671) -TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13219) -TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282125) +TokenPoolWithAllowList_setRouter:test_ZeroAddressNotAllowed_Revert() (gas: 10696) +TokenPool_addRemotePool:test_NonExistentChain_Revert() (gas: 14222) +TokenPool_addRemotePool:test_PoolAlreadyAdded_Revert() (gas: 117183) +TokenPool_addRemotePool:test_ZeroLengthAddressNotAllowed_Revert() (gas: 14037) +TokenPool_addRemotePool:test_addRemotePool_MultipleActive() (gas: 472725) +TokenPool_addRemotePool:test_addRemotePool_Success() (gas: 157106) +TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 455399) +TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 15010) +TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11819) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 592007) +TokenPool_applyChainUpdates:test_applyChainUpdates_UpdatesRemotePoolHashes() (gas: 1077674) +TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 226422) +TokenPool_calculateLocalAmount:test_calculateLocalAmount() (gas: 94754) +TokenPool_calculateLocalAmount:test_calculateLocalAmount_RevertWhen_HighAmountOverflows() (gas: 2731145) +TokenPool_calculateLocalAmount:test_calculateLocalAmount_RevertWhen_HighLocalDecimalsOverflows() (gas: 2730754) +TokenPool_calculateLocalAmount:test_calculateLocalAmount_RevertWhen_HighRemoteDecimalsOverflows() (gas: 9558) +TokenPool_calculateLocalAmount:test_calculateLocalAmount_RevertWhen_LowRemoteDecimalsOverflows() (gas: 2730777) +TokenPool_constructor:test_constructor() (gas: 21909) +TokenPool_constructor:test_constructor_DecimalCallFails() (gas: 2728920) +TokenPool_constructor:test_constructor_RevertWhen_InvalidDecimalArgs() (gas: 77725) +TokenPool_constructor:test_constructor_RevertWhen_ZeroAddressNotAllowed() (gas: 71520) +TokenPool_getRemotePool:test_getRemotePools() (gas: 330178) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21458) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 240293) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 94196) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 21155) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 204261) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 49198) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals() (gas: 13954) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() (gas: 9703) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_RevertWhen_InvalidRemoteChainDecimals_DigitTooLarge() (gas: 10656) +TokenPool_parseRemoteDecimals:test_parseRemoteDecimals_RevertWhen_InvalidRemoteChainDecimals_WrongType() (gas: 11489) +TokenPool_removeRemotePool:test_InvalidRemotePoolForChain_Revert() (gas: 17488) +TokenPool_removeRemotePool:test_NonExistentChain_Revert() (gas: 14244) +TokenPool_removeRemotePool:test_removeRemotePool_Success() (gas: 187979) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17236) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15240) +TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 10936) +TokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 37540) TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17226) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 139085) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 139114) TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 16000) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 244493) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245063) TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16384) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 263419) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 263889) TokenProxy_constructor:test_Constructor() (gas: 13836) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16899) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12706) TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15885) TokenProxy_getFee:test_GetFee_Success() (gas: 90200) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25704) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35481) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30235) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133508) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 478182) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268672) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50952) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98987) +USDCBridgeMigrator_BurnLockedUSDC:test_PrimaryMechanism_Success() (gas: 135852) +USDCBridgeMigrator_BurnLockedUSDC:test_WhileMigrationPause_Revert() (gas: 109729) +USDCBridgeMigrator_BurnLockedUSDC:test_invalidPermissions_Revert() (gas: 39465) +USDCBridgeMigrator_BurnLockedUSDC:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309798) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_Success() (gas: 146961) +USDCBridgeMigrator_BurnLockedUSDC:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209091) +USDCBridgeMigrator_cancelMigrationProposal:test_cancelExistingCCTPMigrationProposal_Success() (gas: 56049) +USDCBridgeMigrator_cancelMigrationProposal:test_cannotCancelANonExistentMigrationProposal_Revert() (gas: 12636) +USDCBridgeMigrator_excludeTokensFromBurn:test_excludeTokensWhenNoMigrationProposalPending_Revert() (gas: 13513) +USDCBridgeMigrator_proposeMigration:test_ChainNotUsingLockRelease_Revert() (gas: 15699) +USDCBridgeMigrator_provideLiquidity:test_PrimaryMechanism_Success() (gas: 135852) +USDCBridgeMigrator_provideLiquidity:test_WhileMigrationPause_Revert() (gas: 109729) +USDCBridgeMigrator_provideLiquidity:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13362) +USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() (gas: 67359) +USDCBridgeMigrator_provideLiquidity:test_cannotProvideLiquidity_AfterMigration_Revert() (gas: 313639) +USDCBridgeMigrator_provideLiquidity:test_invalidPermissions_Revert() (gas: 39444) +USDCBridgeMigrator_provideLiquidity:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309816) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_Success() (gas: 146983) +USDCBridgeMigrator_provideLiquidity:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209108) +USDCBridgeMigrator_releaseOrMint:test_OnLockReleaseMechanism_Success() (gas: 213107) +USDCBridgeMigrator_releaseOrMint:test_WhileMigrationPause_Revert() (gas: 109606) +USDCBridgeMigrator_releaseOrMint:test_incomingMessageWithPrimaryMechanism() (gas: 265839) +USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_destChain_Success() (gas: 150414) +USDCBridgeMigrator_releaseOrMint:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 511552) +USDCBridgeMigrator_updateChainSelectorMechanism:test_PrimaryMechanism_Success() (gas: 135852) +USDCBridgeMigrator_updateChainSelectorMechanism:test_WhileMigrationPause_Revert() (gas: 109729) +USDCBridgeMigrator_updateChainSelectorMechanism:test_cannotRevertChainMechanism_afterMigration_Revert() (gas: 313218) +USDCBridgeMigrator_updateChainSelectorMechanism:test_invalidPermissions_Revert() (gas: 39465) +USDCBridgeMigrator_updateChainSelectorMechanism:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 309798) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_Success() (gas: 146961) +USDCBridgeMigrator_updateChainSelectorMechanism:test_onLockReleaseMechanism_thenSwitchToPrimary_Success() (gas: 209109) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25789) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35274) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29875) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133446) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 433218) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 265601) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 47169) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 95194) USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66393) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11363) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11270) USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10041) \ No newline at end of file diff --git a/contracts/gas-snapshots/liquiditymanager.gas-snapshot b/contracts/gas-snapshots/liquiditymanager.gas-snapshot index 6f67684cfc..48b45672d2 100644 --- a/contracts/gas-snapshots/liquiditymanager.gas-snapshot +++ b/contracts/gas-snapshots/liquiditymanager.gas-snapshot @@ -3,14 +3,14 @@ LiquidityManager_addLiquidity:test_addLiquiditySuccess() (gas: 279154) LiquidityManager_rebalanceLiquidity:test_InsufficientLiquidityReverts() (gas: 206745) LiquidityManager_rebalanceLiquidity:test_InvalidRemoteChainReverts() (gas: 192319) LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess() (gas: 9141768) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 8960797) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 8956003) -LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 8883801) -LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382897) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPoolsSuccess_AlreadyFinalized() (gas: 9306597) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_MultiStageFinalization() (gas: 9301803) +LiquidityManager_rebalanceLiquidity:test_rebalanceBetweenPools_NativeRewrap() (gas: 9231693) +LiquidityManager_rebalanceLiquidity:test_rebalanceLiquiditySuccess() (gas: 382880) LiquidityManager_receive:test_receive_success() (gas: 21182) LiquidityManager_removeLiquidity:test_InsufficientLiquidityReverts() (gas: 184869) LiquidityManager_removeLiquidity:test_OnlyFinanceRoleReverts() (gas: 10872) -LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236342) +LiquidityManager_removeLiquidity:test_removeLiquiditySuccess() (gas: 236324) LiquidityManager_setCrossChainRebalancer:test_OnlyOwnerReverts() (gas: 17005) LiquidityManager_setCrossChainRebalancer:test_ZeroAddressReverts() (gas: 21624) LiquidityManager_setCrossChainRebalancer:test_ZeroChainSelectorReverts() (gas: 13099) @@ -19,7 +19,7 @@ LiquidityManager_setFinanceRole:test_OnlyOwnerReverts() (gas: 10987) LiquidityManager_setFinanceRole:test_setFinanceRoleSuccess() (gas: 21836) LiquidityManager_setLocalLiquidityContainer:test_OnlyOwnerReverts() (gas: 11052) LiquidityManager_setLocalLiquidityContainer:test_ReverstWhen_CalledWithTheZeroAddress() (gas: 10643) -LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3498806) +LiquidityManager_setLocalLiquidityContainer:test_setLocalLiquidityContainerSuccess() (gas: 3847225) LiquidityManager_setMinimumLiquidity:test_OnlyOwnerReverts() (gas: 10925) LiquidityManager_setMinimumLiquidity:test_setMinimumLiquiditySuccess() (gas: 36389) LiquidityManager_withdrawERC20:test_withdrawERC20Reverts() (gas: 180359) diff --git a/contracts/gas-snapshots/shared.gas-snapshot b/contracts/gas-snapshots/shared.gas-snapshot index 247c36c9bc..a606675413 100644 --- a/contracts/gas-snapshots/shared.gas-snapshot +++ b/contracts/gas-snapshots/shared.gas-snapshot @@ -7,6 +7,31 @@ AuthorizedCallers_applyAuthorizedCallerUpdates:test_SkipRemove_Success() (gas: 3 AuthorizedCallers_applyAuthorizedCallerUpdates:test_ZeroAddressNotAllowed_Revert() (gas: 64661) AuthorizedCallers_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 64661) AuthorizedCallers_constructor:test_constructor_Success() (gas: 693193) +BurnMintERC20_approve:test_approve() (gas: 57609) +BurnMintERC20_approve:test_approve_RevertWhen_InvalidAddress() (gas: 11289) +BurnMintERC20_burn:test_BasicBurn() (gas: 153528) +BurnMintERC20_burn:test_burn_RevertWhen_BurnFromZeroAddress() (gas: 43800) +BurnMintERC20_burn:test_burn_RevertWhen_ExceedsBalance() (gas: 21868) +BurnMintERC20_burn:test_burn_RevertWhen_SenderNotBurner() (gas: 67663) +BurnMintERC20_burnFrom:test_BurnFrom() (gas: 57929) +BurnMintERC20_burnFrom:test_burnFrom_RevertWhen_ExceedsBalance() (gas: 35838) +BurnMintERC20_burnFrom:test_burnFrom_RevertWhen_InsufficientAllowance() (gas: 21834) +BurnMintERC20_burnFrom:test_burnFrom_RevertWhen_SenderNotBurner() (gas: 67662) +BurnMintERC20_burnFromAlias:test_burn() (gas: 57973) +BurnMintERC20_burnFromAlias:test_burn_RevertWhen_ExceedsBalance() (gas: 35880) +BurnMintERC20_burnFromAlias:test_burn_RevertWhen_InsufficientAllowance() (gas: 21897) +BurnMintERC20_burnFromAlias:test_burn_RevertWhen_SenderNotBurner() (gas: 67650) +BurnMintERC20_constructor:test_Constructor() (gas: 1680059) +BurnMintERC20_getCCIPAdmin:test_getCCIPAdmin() (gas: 10544) +BurnMintERC20_getCCIPAdmin:test_setCCIPAdmin() (gas: 21562) +BurnMintERC20_grantMintAndBurnRoles:test_GrantMintAndBurnRoles() (gas: 79089) +BurnMintERC20_mint:test_mint() (gas: 101815) +BurnMintERC20_mint:test_mint_RevertWhen_InvalidRecipient() (gas: 66372) +BurnMintERC20_mint:test_mint_RevertWhen_MaxSupplyExceeded() (gas: 50365) +BurnMintERC20_mint:test_mint_RevertWhen_SenderNotMinter() (gas: 65827) +BurnMintERC20_supportsInterface:test_SupportsInterface() (gas: 11202) +BurnMintERC20_transfer:test_transfer() (gas: 42318) +BurnMintERC20_transfer:test_transfer_RevertWhen_InvalidAddress() (gas: 11287) BurnMintERC677_approve:testApproveSuccess() (gas: 55477) BurnMintERC677_approve:testInvalidAddressReverts() (gas: 10653) BurnMintERC677_burn:testBasicBurnSuccess() (gas: 172022) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 2e1072411c..0b1496d391 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -79,10 +79,6 @@ compileContract ccip/pools/LockReleaseTokenPool.sol compileContract ccip/pools/BurnMintTokenPool.sol compileContract ccip/pools/BurnFromMintTokenPool.sol compileContract ccip/pools/BurnWithFromMintTokenPool.sol -compileContract ccip/pools/LockReleaseTokenPoolAndProxy.sol -compileContract ccip/pools/BurnMintTokenPoolAndProxy.sol -compileContract ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol -compileContract ccip/pools/BurnWithFromMintRebasingTokenPool.sol compileContract ccip/pools/TokenPool.sol diff --git a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol index 1ba13a4974..8ce63a12bb 100644 --- a/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnFromMintTokenPool.sol @@ -18,14 +18,15 @@ import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok contract BurnFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { using SafeERC20 for IBurnMintERC20; - string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.0"; + string public constant override typeAndVersion = "BurnFromMintTokenPool 1.5.1"; constructor( IBurnMintERC20 token, + uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, allowlist, rmnProxy, router) { + ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) { // Some tokens allow burning from the sender without approval, but not all do. // To be safe, we approve the pool to burn from the pool. token.safeIncreaseAllowance(address(this), type(uint256).max); diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol index 33026cf005..30203a4ced 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPool.sol @@ -14,14 +14,15 @@ import {TokenPool} from "./TokenPool.sol"; /// If that is expected, please make sure the token's burner/minter roles are adjustable. /// @dev This contract is a variant of BurnMintTokenPool that uses `burn(amount)`. contract BurnMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion { - string public constant override typeAndVersion = "BurnMintTokenPool 1.5.0"; + string public constant override typeAndVersion = "BurnMintTokenPool 1.5.1"; constructor( IBurnMintERC20 token, + uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, allowlist, rmnProxy, router) {} + ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} /// @inheritdoc BurnMintTokenPoolAbstract function _burn( diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol index 6d743ed4a9..b3bbf4ff5e 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol @@ -25,7 +25,10 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { emit Burned(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: _encodeLocalDecimals() + }); } /// @notice Mint tokens from the pool to the recipient @@ -35,11 +38,15 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); + // Calculate the local amount + uint256 localAmount = + _calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData)); + // Mint to the receiver - IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); + IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, localAmount); - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + emit Minted(msg.sender, releaseOrMintIn.receiver, localAmount); - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount}); } } diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol deleted file mode 100644 index 6e3fb0f479..0000000000 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {LegacyPoolWrapper} from "./LegacyPoolWrapper.sol"; - -contract BurnMintTokenPoolAndProxy is ITypeAndVersion, LegacyPoolWrapper { - string public constant override typeAndVersion = "BurnMintTokenPoolAndProxy 1.5.0"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) LegacyPoolWrapper(token, allowlist, rmnProxy, router) {} - - /// @notice Burn the token in the pool - /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - if (!_hasLegacyPool()) { - IBurnMintERC20(address(i_token)).burn(lockOrBurnIn.amount); - } else { - _lockOrBurnLegacy(lockOrBurnIn); - } - - emit Burned(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - /// @notice Mint tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - if (!_hasLegacyPool()) { - IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); - } else { - _releaseOrMintLegacy(releaseOrMintIn); - } - - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } -} diff --git a/contracts/src/v0.8/ccip/pools/BurnWithFromMintRebasingTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnWithFromMintRebasingTokenPool.sol deleted file mode 100644 index 16acdb03b6..0000000000 --- a/contracts/src/v0.8/ccip/pools/BurnWithFromMintRebasingTokenPool.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {BurnWithFromMintTokenPool} from "./BurnWithFromMintTokenPool.sol"; - -/// @notice This pool mints and burns a 3rd-party token. -/// @dev This contract is a variant of BurnMintTokenPool that uses `burn(from, amount)`. -/// @dev This contract supports minting tokens that do not mint the exact amount they are asked to mint. This can be -/// used for rebasing tokens. NOTE: for true rebasing support, the lockOrBurn method must also be updated to support -/// relaying the correct amount. -contract BurnWithFromMintRebasingTokenPool is BurnWithFromMintTokenPool { - error NegativeMintAmount(uint256 amountBurned); - - string public constant override typeAndVersion = "BurnWithFromMintRebasingTokenPool 1.5.0"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) BurnWithFromMintTokenPool(token, allowlist, rmnProxy, router) {} - - /// @notice Mint tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - uint256 balancePre = IBurnMintERC20(address(i_token)).balanceOf(releaseOrMintIn.receiver); - - // Mint to the receiver - IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); - - uint256 balancePost = IBurnMintERC20(address(i_token)).balanceOf(releaseOrMintIn.receiver); - - // Mint should not reduce the number of tokens in the receiver, if it does it will revert the call. - if (balancePost < balancePre) { - revert NegativeMintAmount(balancePre - balancePost); - } - - emit Minted(msg.sender, releaseOrMintIn.receiver, balancePost - balancePre); - - return Pool.ReleaseOrMintOutV1({destinationAmount: balancePost - balancePre}); - } -} diff --git a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol index 37541bb827..fb8538141c 100644 --- a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol @@ -20,10 +20,11 @@ contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion constructor( IBurnMintERC20 token, + uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, allowlist, rmnProxy, router) { + ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) { // Some tokens allow burning from the sender without approval, but not all do. // To be safe, we approve the pool to burn from the pool. token.safeIncreaseAllowance(address(this), type(uint256).max); @@ -37,6 +38,6 @@ contract BurnWithFromMintTokenPool is BurnMintTokenPoolAbstract, ITypeAndVersion } function typeAndVersion() external pure virtual override returns (string memory) { - return "BurnWithFromMintTokenPool 1.5.0"; + return "BurnWithFromMintTokenPool 1.5.1"; } } diff --git a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol deleted file mode 100644 index d9c4df0a6c..0000000000 --- a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; -import {IBurnMintERC20} from "../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {LegacyPoolWrapper} from "./LegacyPoolWrapper.sol"; - -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -contract BurnWithFromMintTokenPoolAndProxy is ITypeAndVersion, LegacyPoolWrapper { - using SafeERC20 for IBurnMintERC20; - - string public constant override typeAndVersion = "BurnWithFromMintTokenPoolAndProxy 1.5.0"; - - constructor( - IBurnMintERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) LegacyPoolWrapper(token, allowlist, rmnProxy, router) { - // Some tokens allow burning from the sender without approval, but not all do. - // To be safe, we approve the pool to burn from the pool. - token.safeIncreaseAllowance(address(this), type(uint256).max); - } - - /// @notice Burn the token in the pool - /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - if (!_hasLegacyPool()) { - IBurnMintERC20(address(i_token)).burnFrom(address(this), lockOrBurnIn.amount); - } else { - _lockOrBurnLegacy(lockOrBurnIn); - } - - emit Burned(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - /// @notice Mint tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - if (!_hasLegacyPool()) { - IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, releaseOrMintIn.amount); - } else { - _releaseOrMintLegacy(releaseOrMintIn); - } - - emit Minted(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } -} diff --git a/contracts/src/v0.8/ccip/pools/LegacyPoolWrapper.sol b/contracts/src/v0.8/ccip/pools/LegacyPoolWrapper.sol deleted file mode 100644 index 90c90369d8..0000000000 --- a/contracts/src/v0.8/ccip/pools/LegacyPoolWrapper.sol +++ /dev/null @@ -1,98 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPoolPriorTo1_5} from "../interfaces/IPoolPriorTo1_5.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {TokenPool} from "./TokenPool.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -abstract contract LegacyPoolWrapper is TokenPool { - using SafeERC20 for IERC20; - - event LegacyPoolChanged(IPoolPriorTo1_5 oldPool, IPoolPriorTo1_5 newPool); - - /// @dev The previous pool, if there is any. This is a property to make the older 1.0-1.4 pools - /// compatible with the current 1.5 pool. To achieve this, we set the previous pool address to the - /// currently deployed legacy pool. Then we configure this new pool as onRamp and offRamp on the legacy pools. - /// In the case of a 1.4 pool, this new pool contract has to be set to the Router as well, as it validates - /// who can call it through the router calls. This contract will always return itself as the only allowed ramp. - /// @dev Can be address(0), this would indicate that this pool is operating as a normal pool as opposed to - /// a proxy pool. - IPoolPriorTo1_5 internal s_previousPool; - - constructor( - IERC20 token, - address[] memory allowlist, - address rmnProxy, - address router - ) TokenPool(token, allowlist, rmnProxy, router) {} - - // ================================================================ - // │ Legacy Fallbacks │ - // ================================================================ - // Legacy fallbacks for older token pools that do not implement the new interface. - - /// @notice Legacy fallback for the 1.4 token pools. - function getOnRamp( - uint64 - ) external view returns (address onRampAddress) { - return address(this); - } - - /// @notice Return true if the given offRamp is a configured offRamp for the given source chain. - function isOffRamp(uint64 sourceChainSelector, address offRamp) external view returns (bool) { - return offRamp == address(this) || s_router.isOffRamp(sourceChainSelector, offRamp); - } - - /// @notice Configures the legacy fallback option. If the previous pool is set, this pool will act as a proxy for - /// the legacy pool. - /// @param prevPool The address of the previous pool. - function setPreviousPool( - IPoolPriorTo1_5 prevPool - ) external onlyOwner { - IPoolPriorTo1_5 oldPrevPool = s_previousPool; - s_previousPool = prevPool; - - emit LegacyPoolChanged(oldPrevPool, prevPool); - } - - /// @notice Returns the address of the previous pool. - function getPreviousPool() external view returns (address) { - return address(s_previousPool); - } - - function _hasLegacyPool() internal view returns (bool) { - return address(s_previousPool) != address(0); - } - - function _lockOrBurnLegacy( - Pool.LockOrBurnInV1 memory lockOrBurnIn - ) internal { - i_token.safeTransfer(address(s_previousPool), lockOrBurnIn.amount); - s_previousPool.lockOrBurn( - lockOrBurnIn.originalSender, lockOrBurnIn.receiver, lockOrBurnIn.amount, lockOrBurnIn.remoteChainSelector, "" - ); - } - - /// @notice This call converts the arguments from a >=1.5 pool call to those of a <1.5 pool call, and uses these - /// to call the previous pool. - /// @param releaseOrMintIn The 1.5 style release or mint arguments. - /// @dev Overwrites the receiver so the previous pool sends the tokens to the sender of this call, which is the - /// offRamp. This is due to the older pools sending funds directly to the receiver, while the new pools do a hop - /// through the offRamp to ensure the correct tokens are sent. - /// @dev Since extraData has never been used in LockRelease or MintBurn token pools, we can safely ignore it. - function _releaseOrMintLegacy( - Pool.ReleaseOrMintInV1 memory releaseOrMintIn - ) internal { - s_previousPool.releaseOrMint( - releaseOrMintIn.originalSender, - releaseOrMintIn.receiver, - releaseOrMintIn.amount, - releaseOrMintIn.remoteChainSelector, - "" - ); - } -} diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol index 0f77304b18..ecc28a14dd 100644 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol @@ -9,6 +9,7 @@ import {TokenPool} from "./TokenPool.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; /// @notice Token pool used for tokens on their native chain. This uses a lock and release mechanism. /// Because of lock/unlock requiring liquidity, this pool contract also has function to add and remove @@ -22,7 +23,7 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion event LiquidityTransferred(address indexed from, uint256 amount); - string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.0"; + string public constant override typeAndVersion = "LockReleaseTokenPool 1.5.1"; /// @dev Whether or not the pool accepts liquidity. /// External liquidity is not required when there is one canonical token deployed to a chain, @@ -34,11 +35,12 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion constructor( IERC20 token, + uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, bool acceptLiquidity, address router - ) TokenPool(token, allowlist, rmnProxy, router) { + ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) { i_acceptLiquidity = acceptLiquidity; } @@ -51,7 +53,10 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion emit Locked(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: _encodeLocalDecimals() + }); } /// @notice Release tokens from the pool to the recipient @@ -61,15 +66,19 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); + // Calculate the local amount + uint256 localAmount = + _calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData)); + // Release to the recipient - getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); + getToken().safeTransfer(releaseOrMintIn.receiver, localAmount); - emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + emit Released(msg.sender, releaseOrMintIn.receiver, localAmount); - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + return Pool.ReleaseOrMintOutV1({destinationAmount: localAmount}); } - // @inheritdoc IERC165 + /// @inheritdoc IERC165 function supportsInterface( bytes4 interfaceId ) public pure virtual override returns (bool) { diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol deleted file mode 100644 index 1671b9650f..0000000000 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol +++ /dev/null @@ -1,143 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityContainer} from "../../liquiditymanager/interfaces/ILiquidityContainer.sol"; -import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; - -import {Pool} from "../libraries/Pool.sol"; -import {LegacyPoolWrapper} from "./LegacyPoolWrapper.sol"; - -import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; - -/// @notice Token pool used for tokens on their native chain. This uses a lock and release mechanism. -/// Because of lock/unlock requiring liquidity, this pool contract also has function to add and remove -/// liquidity. This allows for proper bookkeeping for both user and liquidity provider balances. -/// @dev One token per LockReleaseTokenPool. -contract LockReleaseTokenPoolAndProxy is LegacyPoolWrapper, ILiquidityContainer, ITypeAndVersion { - using SafeERC20 for IERC20; - - error InsufficientLiquidity(); - error LiquidityNotAccepted(); - - string public constant override typeAndVersion = "LockReleaseTokenPoolAndProxy 1.5.0"; - - /// @dev Whether or not the pool accepts liquidity. - /// External liquidity is not required when there is one canonical token deployed to a chain, - /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant - /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold - bool internal immutable i_acceptLiquidity; - /// @notice The address of the rebalancer. - address internal s_rebalancer; - - constructor( - IERC20 token, - address[] memory allowlist, - address rmnProxy, - bool acceptLiquidity, - address router - ) LegacyPoolWrapper(token, allowlist, rmnProxy, router) { - i_acceptLiquidity = acceptLiquidity; - } - - /// @notice Locks the token in the pool - /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn( - Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { - _validateLockOrBurn(lockOrBurnIn); - - if (_hasLegacyPool()) { - _lockOrBurnLegacy(lockOrBurnIn); - } - - emit Locked(msg.sender, lockOrBurnIn.amount); - - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); - } - - /// @notice Release tokens from the pool to the recipient - /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint( - Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - _validateReleaseOrMint(releaseOrMintIn); - - if (!_hasLegacyPool()) { - // Release to the recipient - getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); - } else { - _releaseOrMintLegacy(releaseOrMintIn); - } - - emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); - - return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); - } - - // @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) public pure virtual override returns (bool) { - return interfaceId == type(ILiquidityContainer).interfaceId || super.supportsInterface(interfaceId); - } - - /// @notice Gets LiquidityManager, can be address(0) if none is configured. - /// @return The current liquidity manager. - function getRebalancer() external view returns (address) { - return s_rebalancer; - } - - /// @notice Sets the LiquidityManager address. - /// @dev Only callable by the owner. - function setRebalancer( - address rebalancer - ) external onlyOwner { - s_rebalancer = rebalancer; - } - - /// @notice Checks if the pool can accept liquidity. - /// @return true if the pool can accept liquidity, false otherwise. - function canAcceptLiquidity() external view returns (bool) { - return i_acceptLiquidity; - } - - /// @notice Adds liquidity to the pool. The tokens should be approved first. - /// @param amount The amount of liquidity to provide. - function provideLiquidity( - uint256 amount - ) external { - if (!i_acceptLiquidity) revert LiquidityNotAccepted(); - if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); - - i_token.safeTransferFrom(msg.sender, address(this), amount); - emit LiquidityAdded(msg.sender, amount); - } - - /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. - /// @param amount The amount of liquidity to remove. - function withdrawLiquidity( - uint256 amount - ) external { - if (s_rebalancer != msg.sender) revert Unauthorized(msg.sender); - - if (i_token.balanceOf(address(this)) < amount) revert InsufficientLiquidity(); - i_token.safeTransfer(msg.sender, amount); - emit LiquidityRemoved(msg.sender, amount); - } - - /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so - /// this pool will have to be set as the rebalancer in the older version of the pool. This allows it to transfer the - /// funds in the old pool to the new pool. - /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the - /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. - /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before - /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the - /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its - /// liquidity. Finally, the remaining liquidity can be transferred to the new pool using this function one more time. - /// @param from The address of the old pool. - /// @param amount The amount of liquidity to transfer. - function transferLiquidity(address from, uint256 amount) external onlyOwner { - LockReleaseTokenPoolAndProxy(from).withdrawLiquidity(amount); - } -} diff --git a/contracts/src/v0.8/ccip/pools/TokenPool.sol b/contracts/src/v0.8/ccip/pools/TokenPool.sol index e3b4e92055..cd3096f4ef 100644 --- a/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -5,18 +5,32 @@ import {IPoolV1} from "../interfaces/IPool.sol"; import {IRMN} from "../interfaces/IRMN.sol"; import {IRouter} from "../interfaces/IRouter.sol"; -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {Ownable2StepMsgSender} from "../../shared/access/Ownable2StepMsgSender.sol"; import {Pool} from "../libraries/Pool.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata} from + "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IERC165} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; -/// @notice Base abstract class with common functions for all token pools. -/// A token pool serves as isolated place for holding tokens and token specific logic -/// that may execute as tokens move across the bridge. -abstract contract TokenPool is IPoolV1, OwnerIsCreator { +/// @dev This pool supports different decimals on different chains but using this feature could impact the total number +/// of tokens in circulation. Since all of the tokens are locked/burned on the source, and a rounded amount is minted/released on the +/// destination, the number of tokens minted/released could be less than the number of tokens burned/locked. This is because the source +/// chain does not know about the destination token decimals. This is not a problem if the decimals are the same on both +/// chains. +/// +/// Example: +/// Assume there is a token with 6 decimals on chain A and 3 decimals on chain B. +/// - 1.234567 tokens are burned on chain A. +/// - 1.234 tokens are minted on chain B. +/// When sending the 1.234 tokens back to chain A, you will receive 1.234000 tokens on chain A, effectively losing +/// 0.000567 tokens. +/// In the case of a burnMint pool on chain A, these funds are burned in the pool on chain A. +/// In the case of a lockRelease pool on chain A, these funds accumulate in the pool on chain A. +abstract contract TokenPool is IPoolV1, Ownable2StepMsgSender { + using EnumerableSet for EnumerableSet.Bytes32Set; using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.UintSet; using RateLimiter for RateLimiter.TokenBucket; @@ -32,6 +46,11 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { error InvalidSourcePoolAddress(bytes sourcePoolAddress); error InvalidToken(address token); error Unauthorized(address caller); + error PoolAlreadyAdded(uint64 remoteChainSelector, bytes remotePoolAddress); + error InvalidRemotePoolForChain(uint64 remoteChainSelector, bytes remotePoolAddress); + error InvalidRemoteChainDecimals(bytes sourcePoolData); + error OverflowDetected(uint8 remoteDecimals, uint8 localDecimals, uint256 remoteAmount); + error InvalidDecimalArgs(uint8 expected, uint8 actual); event Locked(address indexed sender, uint256 amount); event Burned(address indexed sender, uint256 amount); @@ -49,16 +68,17 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { RateLimiter.Config inboundRateLimiterConfig ); event ChainRemoved(uint64 remoteChainSelector); - event RemotePoolSet(uint64 indexed remoteChainSelector, bytes previousPoolAddress, bytes remotePoolAddress); + event RemotePoolAdded(uint64 indexed remoteChainSelector, bytes remotePoolAddress); + event RemotePoolRemoved(uint64 indexed remoteChainSelector, bytes remotePoolAddress); event AllowListAdd(address sender); event AllowListRemove(address sender); event RouterUpdated(address oldRouter, address newRouter); + event RateLimitAdminSet(address rateLimitAdmin); struct ChainUpdate { - uint64 remoteChainSelector; // ──╮ Remote chain selector - bool allowed; // ────────────────╯ Whether the chain should be enabled - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. - bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. + uint64 remoteChainSelector; // Remote chain selector + bytes[] remotePoolAddresses; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. + bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. RateLimiter.Config outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain RateLimiter.Config inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain } @@ -66,21 +86,23 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { struct RemoteChainConfig { RateLimiter.TokenBucket outboundRateLimiterConfig; // Outbound rate limited config, meaning the rate limits for all of the onRamps for the given chain RateLimiter.TokenBucket inboundRateLimiterConfig; // Inbound rate limited config, meaning the rate limits for all of the offRamps for the given chain - bytes remotePoolAddress; // Address of the remote pool, ABI encoded in the case of a remote EVM chain. bytes remoteTokenAddress; // Address of the remote token, ABI encoded in the case of a remote EVM chain. + EnumerableSet.Bytes32Set remotePools; // Set of remote pool hashes, ABI encoded in the case of a remote EVM chain. } - /// @dev The bridgeable token that is managed by this pool. + /// @dev The bridgeable token that is managed by this pool. Pools could support multiple tokens at the same time if + /// required, but this implementation only supports one token. IERC20 internal immutable i_token; + /// @dev The number of decimals of the token managed by this pool. + uint8 internal immutable i_tokenDecimals; /// @dev The address of the RMN proxy address internal immutable i_rmnProxy; /// @dev The immutable flag that indicates if the pool is access-controlled. bool internal immutable i_allowlistEnabled; /// @dev A set of addresses allowed to trigger lockOrBurn as original senders. /// Only takes effect if i_allowlistEnabled is true. - /// This can be used to ensure only token-issuer specified addresses can - /// move tokens. - EnumerableSet.AddressSet internal s_allowList; + /// This can be used to ensure only token-issuer specified addresses can move tokens. + EnumerableSet.AddressSet internal s_allowlist; /// @dev The address of the router IRouter internal s_router; /// @dev A set of allowed chain selectors. We want the allowlist to be enumerable to @@ -88,14 +110,28 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @dev The chain selectors are in uint256 format because of the EnumerableSet implementation. EnumerableSet.UintSet internal s_remoteChainSelectors; mapping(uint64 remoteChainSelector => RemoteChainConfig) internal s_remoteChainConfigs; + /// @notice A mapping of hashed pool addresses to their unhashed form. This is used to be able to find the actually + /// configured pools and not just their hashed versions. + mapping(bytes32 poolAddressHash => bytes poolAddress) internal s_remotePoolAddresses; /// @notice The address of the rate limiter admin. /// @dev Can be address(0) if none is configured. address internal s_rateLimitAdmin; - constructor(IERC20 token, address[] memory allowlist, address rmnProxy, address router) { + constructor(IERC20 token, uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router) { if (address(token) == address(0) || router == address(0) || rmnProxy == address(0)) revert ZeroAddressNotAllowed(); i_token = token; i_rmnProxy = rmnProxy; + + try IERC20Metadata(address(token)).decimals() returns (uint8 actualTokenDecimals) { + if (localTokenDecimals != actualTokenDecimals) { + revert InvalidDecimalArgs(localTokenDecimals, actualTokenDecimals); + } + } catch { + // The decimals function doesn't exist, which is possible since it's optional in the ERC20 spec. We skip the check and + // assume the supplied token decimals are correct. + } + i_tokenDecimals = localTokenDecimals; + s_router = IRouter(router); // Pool can be set as permissioned or permissionless at deployment time only to save hot-path gas. @@ -105,12 +141,6 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { } } - /// @notice Get RMN proxy address - /// @return rmnProxy Address of RMN proxy - function getRmnProxy() public view returns (address rmnProxy) { - return i_rmnProxy; - } - /// @inheritdoc IPoolV1 function isSupportedToken( address token @@ -124,6 +154,12 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { return i_token; } + /// @notice Get RMN proxy address + /// @return rmnProxy Address of RMN proxy + function getRmnProxy() public view returns (address rmnProxy) { + return i_rmnProxy; + } + /// @notice Gets the pool's Router /// @return router The pool's Router function getRouter() public view returns (address router) { @@ -164,7 +200,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @dev This function should always be called before executing a lock or burn. Not doing so would allow /// for various exploits. function _validateLockOrBurn( - Pool.LockOrBurnInV1 memory lockOrBurnIn + Pool.LockOrBurnInV1 calldata lockOrBurnIn ) internal { if (!isSupportedToken(lockOrBurnIn.localToken)) revert InvalidToken(lockOrBurnIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(lockOrBurnIn.remoteChainSelector)))) revert CursedByRMN(); @@ -184,23 +220,83 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @dev This function should always be called before executing a release or mint. Not doing so would allow /// for various exploits. function _validateReleaseOrMint( - Pool.ReleaseOrMintInV1 memory releaseOrMintIn + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn ) internal { if (!isSupportedToken(releaseOrMintIn.localToken)) revert InvalidToken(releaseOrMintIn.localToken); if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(releaseOrMintIn.remoteChainSelector)))) revert CursedByRMN(); _onlyOffRamp(releaseOrMintIn.remoteChainSelector); // Validates that the source pool address is configured on this pool. - bytes memory configuredRemotePool = getRemotePool(releaseOrMintIn.remoteChainSelector); - if ( - configuredRemotePool.length == 0 - || keccak256(releaseOrMintIn.sourcePoolAddress) != keccak256(configuredRemotePool) - ) { + if (!isRemotePool(releaseOrMintIn.remoteChainSelector, releaseOrMintIn.sourcePoolAddress)) { revert InvalidSourcePoolAddress(releaseOrMintIn.sourcePoolAddress); } + _consumeInboundRateLimit(releaseOrMintIn.remoteChainSelector, releaseOrMintIn.amount); } + // ================================================================ + // │ Token decimals │ + // ================================================================ + + /// @notice Gets the IERC20 token decimals on the local chain. + function getTokenDecimals() public view virtual returns (uint8 decimals) { + return i_tokenDecimals; + } + + function _encodeLocalDecimals() internal view virtual returns (bytes memory) { + return abi.encode(i_tokenDecimals); + } + + function _parseRemoteDecimals( + bytes memory sourcePoolData + ) internal view virtual returns (uint8) { + // Fallback to the local token decimals if the source pool data is empty. This allows for backwards compatibility. + if (sourcePoolData.length == 0) { + return i_tokenDecimals; + } + if (sourcePoolData.length != 32) { + revert InvalidRemoteChainDecimals(sourcePoolData); + } + uint256 remoteDecimals = abi.decode(sourcePoolData, (uint256)); + if (remoteDecimals > type(uint8).max) { + revert InvalidRemoteChainDecimals(sourcePoolData); + } + return uint8(remoteDecimals); + } + + /// @notice Calculates the local amount based on the remote amount and decimals. + /// @param remoteAmount The amount on the remote chain. + /// @param remoteDecimals The decimals of the token on the remote chain. + /// @return The local amount. + /// @dev This function protects against overflows. If there is a transaction that hits the overflow check, it is + /// probably incorrect as that means the amount cannot be represented on this chain. If the local decimals have been + /// wrongly configured, the token issuer could redeploy the pool with the correct decimals and manually re-execute the + /// CCIP tx to fix the issue. + function _calculateLocalAmount(uint256 remoteAmount, uint8 remoteDecimals) internal view virtual returns (uint256) { + if (remoteDecimals == i_tokenDecimals) { + return remoteAmount; + } + if (remoteDecimals > i_tokenDecimals) { + uint8 decimalsDiff = remoteDecimals - i_tokenDecimals; + if (decimalsDiff > 77) { + // This is a safety check to prevent overflow in the next calculation. + revert OverflowDetected(remoteDecimals, i_tokenDecimals, remoteAmount); + } + // Solidity rounds down so there is no risk of minting more tokens than the remote chain sent. + return remoteAmount / (10 ** decimalsDiff); + } + + // This is a safety check to prevent overflow in the next calculation. + // More than 77 would never fit in a uint256 and would cause an overflow. We also check if the resulting amount + // would overflow. + uint8 diffDecimals = i_tokenDecimals - remoteDecimals; + if (diffDecimals > 77 || remoteAmount > type(uint256).max / (10 ** diffDecimals)) { + revert OverflowDetected(remoteDecimals, i_tokenDecimals, remoteAmount); + } + + return remoteAmount * (10 ** diffDecimals); + } + // ================================================================ // │ Chain permissions │ // ================================================================ @@ -208,10 +304,24 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Gets the pool address on the remote chain. /// @param remoteChainSelector Remote chain selector. /// @dev To support non-evm chains, this value is encoded into bytes - function getRemotePool( + function getRemotePools( uint64 remoteChainSelector - ) public view returns (bytes memory) { - return s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; + ) public view returns (bytes[] memory) { + bytes32[] memory remotePoolHashes = s_remoteChainConfigs[remoteChainSelector].remotePools.values(); + + bytes[] memory remotePools = new bytes[](remotePoolHashes.length); + for (uint256 i = 0; i < remotePoolHashes.length; ++i) { + remotePools[i] = s_remotePoolAddresses[remotePoolHashes[i]]; + } + + return remotePools; + } + + /// @notice Checks if the pool address is configured on the remote chain. + /// @param remoteChainSelector Remote chain selector. + /// @param remotePoolAddress The address of the remote pool. + function isRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) public view returns (bool) { + return s_remoteChainConfigs[remoteChainSelector].remotePools.contains(keccak256(remotePoolAddress)); } /// @notice Gets the token address on the remote chain. @@ -223,16 +333,28 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { return s_remoteChainConfigs[remoteChainSelector].remoteTokenAddress; } - /// @notice Sets the remote pool address for a given chain selector. - /// @param remoteChainSelector The remote chain selector for which the remote pool address is being set. - /// @param remotePoolAddress The address of the remote pool. - function setRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { + /// @notice Adds a remote pool for a given chain selector. This could be due to a pool being upgraded on the remote + /// chain. We don't simply want to replace the old pool as there could still be valid inflight messages from the old + /// pool. This function allows for multiple pools to be added for a single chain selector. + /// @param remoteChainSelector The remote chain selector for which the remote pool address is being added. + /// @param remotePoolAddress The address of the new remote pool. + function addRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); - bytes memory prevAddress = s_remoteChainConfigs[remoteChainSelector].remotePoolAddress; - s_remoteChainConfigs[remoteChainSelector].remotePoolAddress = remotePoolAddress; + _setRemotePool(remoteChainSelector, remotePoolAddress); + } - emit RemotePoolSet(remoteChainSelector, prevAddress, remotePoolAddress); + /// @notice Removes the remote pool address for a given chain selector. + /// @dev All inflight txs from the remote pool will be rejected after it is removed. To ensure no loss of funds, there + /// should be no inflight txs from the given pool. + function removeRemotePool(uint64 remoteChainSelector, bytes calldata remotePoolAddress) external onlyOwner { + if (!isSupportedChain(remoteChainSelector)) revert NonExistentChain(remoteChainSelector); + + if (!s_remoteChainConfigs[remoteChainSelector].remotePools.remove(keccak256(remotePoolAddress))) { + revert InvalidRemotePoolForChain(remoteChainSelector, remotePoolAddress); + } + + emit RemotePoolRemoved(remoteChainSelector, remotePoolAddress); } /// @inheritdoc IPoolV1 @@ -256,69 +378,120 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Sets the permissions for a list of chains selectors. Actual senders for these chains /// need to be allowed on the Router to interact with this pool. - /// @dev Only callable by the owner - /// @param chains A list of chains and their new permission status & rate limits. Rate limits + /// @param remoteChainSelectorsToRemove A list of chain selectors to remove. + /// @param chainsToAdd A list of chains and their new permission status & rate limits. Rate limits /// are only used when the chain is being added through `allowed` being true. + /// @dev Only callable by the owner function applyChainUpdates( - ChainUpdate[] calldata chains + uint64[] calldata remoteChainSelectorsToRemove, + ChainUpdate[] calldata chainsToAdd ) external virtual onlyOwner { - for (uint256 i = 0; i < chains.length; ++i) { - ChainUpdate memory update = chains[i]; - RateLimiter._validateTokenBucketConfig(update.outboundRateLimiterConfig, !update.allowed); - RateLimiter._validateTokenBucketConfig(update.inboundRateLimiterConfig, !update.allowed); - - if (update.allowed) { - // If the chain already exists, revert - if (!s_remoteChainSelectors.add(update.remoteChainSelector)) { - revert ChainAlreadyExists(update.remoteChainSelector); - } - - if (update.remotePoolAddress.length == 0 || update.remoteTokenAddress.length == 0) { - revert ZeroAddressNotAllowed(); - } - - s_remoteChainConfigs[update.remoteChainSelector] = RemoteChainConfig({ - outboundRateLimiterConfig: RateLimiter.TokenBucket({ - rate: update.outboundRateLimiterConfig.rate, - capacity: update.outboundRateLimiterConfig.capacity, - tokens: update.outboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.outboundRateLimiterConfig.isEnabled - }), - inboundRateLimiterConfig: RateLimiter.TokenBucket({ - rate: update.inboundRateLimiterConfig.rate, - capacity: update.inboundRateLimiterConfig.capacity, - tokens: update.inboundRateLimiterConfig.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: update.inboundRateLimiterConfig.isEnabled - }), - remotePoolAddress: update.remotePoolAddress, - remoteTokenAddress: update.remoteTokenAddress - }); - - emit ChainAdded( - update.remoteChainSelector, - update.remoteTokenAddress, - update.outboundRateLimiterConfig, - update.inboundRateLimiterConfig - ); - } else { - // If the chain doesn't exist, revert - if (!s_remoteChainSelectors.remove(update.remoteChainSelector)) { - revert NonExistentChain(update.remoteChainSelector); - } - - delete s_remoteChainConfigs[update.remoteChainSelector]; - - emit ChainRemoved(update.remoteChainSelector); + for (uint256 i = 0; i < remoteChainSelectorsToRemove.length; ++i) { + uint64 remoteChainSelectorToRemove = remoteChainSelectorsToRemove[i]; + // If the chain doesn't exist, revert + if (!s_remoteChainSelectors.remove(remoteChainSelectorToRemove)) { + revert NonExistentChain(remoteChainSelectorToRemove); } + + // Remove all remote pool hashes for the chain + bytes32[] memory remotePools = s_remoteChainConfigs[remoteChainSelectorToRemove].remotePools.values(); + for (uint256 j = 0; j < remotePools.length; ++j) { + s_remoteChainConfigs[remoteChainSelectorToRemove].remotePools.remove(remotePools[j]); + } + + delete s_remoteChainConfigs[remoteChainSelectorToRemove]; + + emit ChainRemoved(remoteChainSelectorToRemove); + } + + for (uint256 i = 0; i < chainsToAdd.length; ++i) { + ChainUpdate memory newChain = chainsToAdd[i]; + RateLimiter._validateTokenBucketConfig(newChain.outboundRateLimiterConfig, false); + RateLimiter._validateTokenBucketConfig(newChain.inboundRateLimiterConfig, false); + + if (newChain.remoteTokenAddress.length == 0) { + revert ZeroAddressNotAllowed(); + } + + // If the chain already exists, revert + if (!s_remoteChainSelectors.add(newChain.remoteChainSelector)) { + revert ChainAlreadyExists(newChain.remoteChainSelector); + } + + RemoteChainConfig storage remoteChainConfig = s_remoteChainConfigs[newChain.remoteChainSelector]; + + remoteChainConfig.outboundRateLimiterConfig = RateLimiter.TokenBucket({ + rate: newChain.outboundRateLimiterConfig.rate, + capacity: newChain.outboundRateLimiterConfig.capacity, + tokens: newChain.outboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: newChain.outboundRateLimiterConfig.isEnabled + }); + remoteChainConfig.inboundRateLimiterConfig = RateLimiter.TokenBucket({ + rate: newChain.inboundRateLimiterConfig.rate, + capacity: newChain.inboundRateLimiterConfig.capacity, + tokens: newChain.inboundRateLimiterConfig.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: newChain.inboundRateLimiterConfig.isEnabled + }); + remoteChainConfig.remoteTokenAddress = newChain.remoteTokenAddress; + + for (uint256 j = 0; j < newChain.remotePoolAddresses.length; ++j) { + _setRemotePool(newChain.remoteChainSelector, newChain.remotePoolAddresses[j]); + } + + emit ChainAdded( + newChain.remoteChainSelector, + newChain.remoteTokenAddress, + newChain.outboundRateLimiterConfig, + newChain.inboundRateLimiterConfig + ); } } + /// @notice Adds a pool address to the allowed remote token pools for a particular chain. + /// @param remoteChainSelector The remote chain selector for which the remote pool address is being added. + /// @param remotePoolAddress The address of the new remote pool. + function _setRemotePool(uint64 remoteChainSelector, bytes memory remotePoolAddress) internal { + if (remotePoolAddress.length == 0) { + revert ZeroAddressNotAllowed(); + } + + bytes32 poolHash = keccak256(remotePoolAddress); + + // Check if the pool already exists. + if (!s_remoteChainConfigs[remoteChainSelector].remotePools.add(poolHash)) { + revert PoolAlreadyAdded(remoteChainSelector, remotePoolAddress); + } + + // Add the pool to the mapping to be able to un-hash it later. + s_remotePoolAddresses[poolHash] = remotePoolAddress; + + emit RemotePoolAdded(remoteChainSelector, remotePoolAddress); + } + // ================================================================ // │ Rate limiting │ // ================================================================ + /// @dev The inbound rate limits should be slightly higher than the outbound rate limits. This is because many chains + /// finalize blocks in batches. CCIP also commits messages in batches: the commit plugin bundles multiple messages in + /// a single merkle root. + /// Imagine the following scenario. + /// - Chain A has an inbound and outbound rate limit of 100 tokens capacity and 1 token per second refill rate. + /// - Chain B has an inbound and outbound rate limit of 100 tokens capacity and 1 token per second refill rate. + /// + /// At time 0: + /// - Chain A sends 100 tokens to Chain B. + /// At time 5: + /// - Chain A sends 5 tokens to Chain B. + /// At time 6: + /// The epoch that contains blocks [0-5] is finalized. + /// Both transactions will be included in the same merkle root and become executable at the same time. This means + /// the token pool on chain B requires a capacity of 105 to successfully execute both messages at the same time. + /// The exact additional capacity required depends on the refill rate and the size of the source chain epochs and the + /// CCIP round time. For simplicity, a 5-10% buffer should be sufficient in most cases. + /// @notice Sets the rate limiter admin address. /// @dev Only callable by the owner. /// @param rateLimitAdmin The new rate limiter admin address. @@ -326,6 +499,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { address rateLimitAdmin ) external onlyOwner { s_rateLimitAdmin = rateLimitAdmin; + emit RateLimitAdminSet(rateLimitAdmin); } /// @notice Gets the rate limiter admin address. @@ -416,13 +590,13 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { address sender ) internal view { if (i_allowlistEnabled) { - if (!s_allowList.contains(sender)) { + if (!s_allowlist.contains(sender)) { revert SenderNotAllowed(sender); } } } - /// @notice Gets whether the allowList functionality is enabled. + /// @notice Gets whether the allowlist functionality is enabled. /// @return true is enabled, false if not. function getAllowListEnabled() external view returns (bool) { return i_allowlistEnabled; @@ -431,7 +605,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Gets the allowed addresses. /// @return The allowed addresses. function getAllowList() external view returns (address[] memory) { - return s_allowList.values(); + return s_allowlist.values(); } /// @notice Apply updates to the allow list. @@ -447,7 +621,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { for (uint256 i = 0; i < removes.length; ++i) { address toRemove = removes[i]; - if (s_allowList.remove(toRemove)) { + if (s_allowlist.remove(toRemove)) { emit AllowListRemove(toRemove); } } @@ -456,7 +630,7 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { if (toAdd == address(0)) { continue; } - if (s_allowList.add(toAdd)) { + if (s_allowlist.add(toAdd)) { emit AllowListAdd(toAdd); } } diff --git a/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol new file mode 100644 index 0000000000..746df9b4e1 --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {Pool} from "../../libraries/Pool.sol"; +import {BurnMintTokenPool} from "../BurnMintTokenPool.sol"; +import {LOCK_RELEASE_FLAG} from "./HybridLockReleaseUSDCTokenPool.sol"; + +/// @notice A standard BurnMintTokenPool with modified destPoolData so that the remote pool knows to release tokens +/// instead of minting. This enables interoperability with HybridLockReleaseUSDCTokenPool which uses +// the destPoolData to determine whether to mint or release tokens. +/// @dev The only difference between this contract and BurnMintTokenPool is the destPoolData returns the +/// abi-encoded LOCK_RELEASE_FLAG instead of an empty string. +contract BurnMintWithLockReleaseFlagTokenPool is BurnMintTokenPool { + constructor( + IBurnMintERC20 token, + uint8 localTokenDecimals, + address[] memory allowlist, + address rmnProxy, + address router + ) BurnMintTokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} + + /// @notice Burn the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + /// @dev Performs the exact same functionality as BurnMintTokenPool, but returns the LOCK_RELEASE_FLAG + /// as the destPoolData to signal to the remote pool to release tokens instead of minting them. + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + + _burn(lockOrBurnIn.amount); + + emit Burned(msg.sender, lockOrBurnIn.amount); + + // LOCK_RELEASE_FLAG = bytes4(keccak256("NO_CCTP_USE_LOCK_RELEASE")) + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: abi.encode(LOCK_RELEASE_FLAG) + }); + } +} diff --git a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol index 3691ef1c7b..264b1230c7 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; -import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {Ownable2StepMsgSender} from "../../../shared/access/Ownable2StepMsgSender.sol"; import {Pool} from "../../libraries/Pool.sol"; import {TokenPool} from "../TokenPool.sol"; import {USDCTokenPool} from "../USDC/USDCTokenPool.sol"; @@ -14,6 +14,9 @@ import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/tok import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; +// bytes4(keccak256("NO_CCTP_USE_LOCK_RELEASE")) +bytes4 constant LOCK_RELEASE_FLAG = 0xfa7c07de; + /// @notice A token pool for USDC which uses CCTP for supported chains and Lock/Release for all others /// @dev The functionality from LockReleaseTokenPool.sol has been duplicated due to lack of compiler support for shared /// constructors between parents @@ -34,9 +37,6 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { error LanePausedForCCTPMigration(uint64 remoteChainSelector); error TokenLockingNotAllowedAfterMigration(uint64 remoteChainSelector); - /// bytes4(keccak256("NO_CTTP_USE_LOCK_RELEASE")) - bytes4 public constant LOCK_RELEASE_FLAG = 0xd43c7897; - /// @notice The address of the liquidity provider for a specific chain. /// External liquidity is not required when there is one canonical token deployed to a chain, /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant @@ -49,7 +49,7 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { address[] memory allowlist, address rmnProxy, address router - ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) USDCBridgeMigrator(address(token), router) {} + ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) USDCBridgeMigrator(address(token)) {} // ================================================================ // │ Incoming/Outgoing Mechanisms | @@ -81,7 +81,7 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { // Use CCTP Burn/Mint mechanism for chains which have it enabled. The LOCK_RELEASE_FLAG is used in sourcePoolData to // discern this, since the source-chain will not be a hybrid-pool but a standard burn-mint. In the event of a - // stuck message after a migration has occured, and the message was not executed properly before the migration + // stuck message after a migration has occurred, and the message was not executed properly before the migration // began, and locked tokens were not released until now, the message will already have been committed to with this // flag so it is safe to release the tokens. The source USDC pool is trusted to send messages with the correct // flag as well. @@ -99,7 +99,7 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { _validateReleaseOrMint(releaseOrMintIn); // Circle requires a supply-lock to prevent incoming messages once the migration process begins. - // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + // This prevents new incoming messages once the migration has begun to ensure any the procedure runs as expected if (s_proposedUSDCMigrationChain == releaseOrMintIn.remoteChainSelector) { revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); } @@ -114,7 +114,6 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; } - // Release to the offRamp, which forwards it to the recipient getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); @@ -173,6 +172,16 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { function provideLiquidity(uint64 remoteChainSelector, uint256 amount) external { if (s_liquidityProvider[remoteChainSelector] != msg.sender) revert TokenPool.Unauthorized(msg.sender); + // Prevent adding liquidity to a chain which has already been migrated + if (s_migratedChains.contains(remoteChainSelector)) { + revert TokenLockingNotAllowedAfterMigration(remoteChainSelector); + } + + // prevent adding liquidity to a chain which has been proposed for migration + if (remoteChainSelector == s_proposedUSDCMigrationChain) { + revert LanePausedForCCTPMigration(remoteChainSelector); + } + s_lockedTokensByChainSelector[remoteChainSelector] += amount; i_token.safeTransferFrom(msg.sender, address(this), amount); @@ -187,7 +196,7 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { /// withdrawn on this chain, otherwise a mismatch may occur between locked token balance and remote circulating supply /// which may block a potential future migration of the chain to CCTP. function withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) external onlyOwner { - // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. + // A supply-lock is required to prevent outgoing messages once the migration process begins. // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected if (remoteChainSelector == s_proposedUSDCMigrationChain) { revert LanePausedForCCTPMigration(remoteChainSelector); @@ -213,16 +222,10 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { /// @param from The address of the old pool. /// @param remoteChainSelector The chain for which liquidity is being transferred. function transferLiquidity(address from, uint64 remoteChainSelector) external onlyOwner { - // Prevent Liquidity Transfers when a migration is pending. This prevents requiring the new pool to manage - // token exclusions for edge-case messages and ensures that the migration is completed before any new liquidity - // is added to the pool. - if (HybridLockReleaseUSDCTokenPool(from).getCurrentProposedCCTPChainMigration() == remoteChainSelector) { - revert LanePausedForCCTPMigration(remoteChainSelector); - } - - OwnerIsCreator(from).acceptOwnership(); + Ownable2StepMsgSender(from).acceptOwnership(); - // Withdraw all available liquidity from the old pool. + // Withdraw all available liquidity from the old pool. No check is needed for pending migrations, as the old pool + // will revert if the migration has begun. uint256 withdrawAmount = HybridLockReleaseUSDCTokenPool(from).getLockedTokensForChain(remoteChainSelector); HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, withdrawAmount); @@ -237,16 +240,17 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { /// @notice Return whether a lane should use the alternative L/R mechanism in the token pool. /// @param remoteChainSelector the remote chain the lane is interacting with - /// @return bool Return true if the alternative L/R mechanism should be used + /// @return bool Return true if the alternative L/R mechanism should be used, and is decided by the Owner function shouldUseLockRelease( uint64 remoteChainSelector ) public view virtual returns (bool) { return s_shouldUseLockRelease[remoteChainSelector]; } - /// @notice Updates Updates designations for chains on whether to use primary or alt mechanism on CCIP messages + /// @notice Updates designations for chains on whether to use primary or alt mechanism on CCIP messages /// @param removes A list of chain selectors to disable Lock-Release, and enforce BM - /// @param adds A list of chain selectors to enable LR instead of BM + /// @param adds A list of chain selectors to enable LR instead of BM. These chains must not have been migrated + /// to CCTP yet or the transaction will revert function updateChainSelectorMechanisms(uint64[] calldata removes, uint64[] calldata adds) external onlyOwner { for (uint256 i = 0; i < removes.length; ++i) { delete s_shouldUseLockRelease[removes[i]]; @@ -254,6 +258,10 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { } for (uint256 i = 0; i < adds.length; ++i) { + // Prevent enabling lock release on chains which have already been migrated + if (s_migratedChains.contains(adds[i])) { + revert TokenLockingNotAllowedAfterMigration(adds[i]); + } s_shouldUseLockRelease[adds[i]] = true; emit LockReleaseEnabled(adds[i]); } diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol index 4737a83344..1dcecac8b2 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol @@ -1,16 +1,15 @@ -pragma solidity ^0.8.24; +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; -import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {Ownable2StepMsgSender} from "../../../shared/access/Ownable2StepMsgSender.sol"; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; -import {Router} from "../../Router.sol"; - /// @notice Allows migration of a lane in a token pool from Lock/Release to CCTP supported Burn/Mint. Contract /// functionality is based on hard requirements defined by Circle to allow for future CCTP compatibility /// https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md -abstract contract USDCBridgeMigrator is OwnerIsCreator { +abstract contract USDCBridgeMigrator is Ownable2StepMsgSender { using EnumerableSet for EnumerableSet.UintSet; event CCTPMigrationProposed(uint64 remoteChainSelector); @@ -23,12 +22,10 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { error onlyCircle(); error ExistingMigrationProposal(); - error NoExistingMigrationProposal(); error NoMigrationProposalPending(); - error InvalidChainSelector(uint64 remoteChainSelector); + error InvalidChainSelector(); - IBurnMintERC20 internal immutable i_USDC; - Router internal immutable i_router; + IBurnMintERC20 private immutable i_USDC; address internal s_circleUSDCMigrator; uint64 internal s_proposedUSDCMigrationChain; @@ -38,9 +35,12 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { mapping(uint64 chainSelector => bool shouldUseLockRelease) internal s_shouldUseLockRelease; - constructor(address token, address router) { + EnumerableSet.UintSet internal s_migratedChains; + + constructor( + address token + ) { i_USDC = IBurnMintERC20(token); - i_router = Router(router); } /// @notice Burn USDC locked for a specific lane so that destination USDC can be converted from @@ -49,9 +49,9 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { /// @dev proposeCCTPMigration must be called first on an approved lane to execute properly. /// @dev This function signature should NEVER be overwritten, otherwise it will be unable to be called by /// circle to properly migrate USDC over to CCTP. - function burnLockedUSDC() public { + function burnLockedUSDC() external { if (msg.sender != s_circleUSDCMigrator) revert onlyCircle(); - if (s_proposedUSDCMigrationChain == 0) revert ExistingMigrationProposal(); + if (s_proposedUSDCMigrationChain == 0) revert NoMigrationProposalPending(); uint64 burnChainSelector = s_proposedUSDCMigrationChain; @@ -71,6 +71,8 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { // Disable L/R automatically on burned chain and enable CCTP delete s_shouldUseLockRelease[burnChainSelector]; + s_migratedChains.add(burnChainSelector); + emit CCTPMigrationExecuted(burnChainSelector, tokensToBurn); } @@ -86,6 +88,9 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { // Prevent overwriting existing migration proposals until the current one is finished if (s_proposedUSDCMigrationChain != 0) revert ExistingMigrationProposal(); + // Ensure that the chain is currently using lock/release and not CCTP + if (!s_shouldUseLockRelease[remoteChainSelector]) revert InvalidChainSelector(); + s_proposedUSDCMigrationChain = remoteChainSelector; emit CCTPMigrationProposed(remoteChainSelector); @@ -94,7 +99,7 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { /// @notice Cancel an existing proposal to migrate a lane to CCTP. /// @notice This function will revert if no proposal is currently in progress. function cancelExistingCCTPMigrationProposal() external onlyOwner { - if (s_proposedUSDCMigrationChain == 0) revert NoExistingMigrationProposal(); + if (s_proposedUSDCMigrationChain == 0) revert NoMigrationProposalPending(); uint64 currentProposalChainSelector = s_proposedUSDCMigrationChain; delete s_proposedUSDCMigrationChain; @@ -142,6 +147,8 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { /// @dev This function should ONLY be called on the home chain, where tokens are locked, NOT on the remote chain /// and strict scrutiny should be applied to ensure that the amount of tokens excluded is accurate. function excludeTokensFromBurn(uint64 remoteChainSelector, uint256 amount) external onlyOwner { + if (s_proposedUSDCMigrationChain != remoteChainSelector) revert NoMigrationProposalPending(); + s_tokensExcludedFromBurn[remoteChainSelector] += amount; uint256 burnableAmountAfterExclusion = @@ -156,7 +163,7 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { /// @return uint256 amount of tokens excluded from being burned in a CCTP-migration function getExcludedTokensByChain( uint64 remoteChainSelector - ) public view returns (uint256) { + ) external view returns (uint256) { return s_tokensExcludedFromBurn[remoteChainSelector]; } } diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol index addfe06da0..5998e52f15 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol @@ -50,7 +50,7 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { uint32 sourceDomain; } - string public constant override typeAndVersion = "USDCTokenPool 1.5.0"; + string public constant override typeAndVersion = "USDCTokenPool 1.5.1"; // We restrict to the first version. New pool may be required for subsequent versions. uint32 public constant SUPPORTED_USDC_VERSION = 0; @@ -78,7 +78,7 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, allowlist, rmnProxy, router) { + ) TokenPool(token, 6, allowlist, rmnProxy, router) { if (address(tokenMessenger) == address(0)) revert InvalidConfig(); IMessageTransmitter transmitter = IMessageTransmitter(tokenMessenger.localMessageTransmitter()); uint32 transmitterVersion = transmitter.version(); @@ -126,7 +126,7 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { /// @notice Mint tokens from the pool to the recipient /// * sourceTokenData is part of the verified message and passed directly from - /// the offramp so it is guaranteed to be what the lockOrBurn pool released on the + /// the offRamp so it is guaranteed to be what the lockOrBurn pool released on the /// source chain. It contains (nonce, sourceDomain) which is guaranteed by CCTP /// to be unique. /// * offchainTokenData is untrusted (can be supplied by manual execution), but we assert diff --git a/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/contracts/src/v0.8/ccip/test/BaseTest.t.sol index 4a425af97f..2bffe9c143 100644 --- a/contracts/src/v0.8/ccip/test/BaseTest.t.sol +++ b/contracts/src/v0.8/ccip/test/BaseTest.t.sol @@ -42,6 +42,7 @@ contract BaseTest is Test { uint16 internal constant DEFAULT_TOKEN_FEE_USD_CENTS = 50; uint32 internal constant DEFAULT_TOKEN_DEST_GAS_OVERHEAD = 90_000; uint32 internal constant DEFAULT_TOKEN_BYTES_OVERHEAD = 32; + uint8 internal constant DEFAULT_TOKEN_DECIMALS = 18; bool private s_baseTestInitialized; diff --git a/contracts/src/v0.8/ccip/test/TokenSetup.t.sol b/contracts/src/v0.8/ccip/test/TokenSetup.t.sol index 203145881e..4996b0b740 100644 --- a/contracts/src/v0.8/ccip/test/TokenSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/TokenSetup.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {BurnMintERC677} from "../../shared/token/ERC677/BurnMintERC677.sol"; +import {BurnMintERC20} from "../../shared/token/ERC20/BurnMintERC20.sol"; import {Client} from "../libraries/Client.sol"; import {BurnMintTokenPool} from "../pools/BurnMintTokenPool.sol"; import {LockReleaseTokenPool} from "../pools/LockReleaseTokenPool.sol"; @@ -27,14 +27,14 @@ contract TokenSetup is RouterSetup { mapping(address sourceToken => address destToken) internal s_destTokenBySourceToken; function _deploySourceToken(string memory tokenName, uint256 dealAmount, uint8 decimals) internal returns (address) { - BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, decimals, 0); + BurnMintERC20 token = new BurnMintERC20(tokenName, tokenName, decimals, 0, 0); s_sourceTokens.push(address(token)); deal(address(token), OWNER, dealAmount); return address(token); } function _deployDestToken(string memory tokenName, uint256 dealAmount) internal returns (address) { - BurnMintERC677 token = new BurnMintERC677(tokenName, tokenName, 18, 0); + BurnMintERC20 token = new BurnMintERC20(tokenName, tokenName, 18, 0, 0); s_destTokens.push(address(token)); deal(address(token), OWNER, dealAmount); return address(token); @@ -46,8 +46,9 @@ contract TokenSetup is RouterSetup { router = address(s_destRouter); } - LockReleaseTokenPool pool = - new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, router); + LockReleaseTokenPool pool = new LockReleaseTokenPool( + IERC20(token), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, router + ); if (isSourcePool) { s_sourcePoolByToken[address(token)] = address(pool); @@ -63,9 +64,10 @@ contract TokenSetup is RouterSetup { router = address(s_destRouter); } - BurnMintTokenPool pool = - new MaybeRevertingBurnMintTokenPool(BurnMintERC677(token), new address[](0), address(s_mockRMN), router); - BurnMintERC677(token).grantMintAndBurnRoles(address(pool)); + BurnMintTokenPool pool = new MaybeRevertingBurnMintTokenPool( + BurnMintERC20(token), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), router + ); + BurnMintERC20(token).grantMintAndBurnRoles(address(pool)); if (isSourcePool) { s_sourcePoolByToken[address(token)] = address(pool); @@ -136,18 +138,6 @@ contract TokenSetup is RouterSetup { } } - function _getCastedSourceEVMTokenAmountsWithZeroAmounts() - internal - view - returns (Client.EVMTokenAmount[] memory tokenAmounts) - { - tokenAmounts = new Client.EVMTokenAmount[](s_sourceTokens.length); - for (uint256 i = 0; i < tokenAmounts.length; ++i) { - tokenAmounts[i].token = s_sourceTokens[i]; - } - return tokenAmounts; - } - function _setPool( TokenAdminRegistry tokenAdminRegistry, address token, @@ -163,16 +153,30 @@ contract TokenSetup is RouterSetup { tokenAdminRegistry.setPool(token, pool); + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(remotePoolAddress); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: remoteChainSelector, - remotePoolAddress: abi.encode(remotePoolAddress), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(remoteToken), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - TokenPool(pool).applyChainUpdates(chainUpdates); + TokenPool(pool).applyChainUpdates(new uint64[](0), chainUpdates); + } + + function _getCastedSourceEVMTokenAmountsWithZeroAmounts() + internal + view + returns (Client.EVMTokenAmount[] memory tokenAmounts) + { + tokenAmounts = new Client.EVMTokenAmount[](s_sourceTokens.length); + for (uint256 i = 0; i < tokenAmounts.length; ++i) { + tokenAmounts[i].token = s_sourceTokens[i]; + } + return tokenAmounts; } } diff --git a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol index 4700d7edea..63b22cc12c 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol @@ -30,19 +30,22 @@ contract MultiOnRampTokenPoolReentrancy is OnRampSetup { new FacadeClient(address(s_sourceRouter), DEST_CHAIN_SELECTOR, s_sourceToken, s_feeToken, i_receiver); s_maliciousTokenPool = new ReentrantMaliciousTokenPool( - address(s_facadeClient), s_sourceToken, address(s_mockRMN), address(s_sourceRouter) + address(s_facadeClient), s_sourceToken, DEFAULT_TOKEN_DECIMALS, address(s_mockRMN), address(s_sourceRouter) ); + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(s_destTokens[0]), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_maliciousTokenPool.applyChainUpdates(chainUpdates); + + s_maliciousTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); Internal.PoolUpdate[] memory removes = new Internal.PoolUpdate[](1); diff --git a/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol b/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol index 03db40a293..71a7d7cf42 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/OnRampTokenPoolReentrancy.t.sol @@ -30,19 +30,21 @@ contract OnRampTokenPoolReentrancy is EVM2EVMOnRampSetup { new FacadeClient(address(s_sourceRouter), DEST_CHAIN_SELECTOR, s_sourceToken, s_feeToken, i_receiver); s_maliciousTokenPool = new ReentrantMaliciousTokenPool( - address(s_facadeClient), s_sourceToken, address(s_mockRMN), address(s_sourceRouter) + address(s_facadeClient), s_sourceToken, DEFAULT_TOKEN_DECIMALS, address(s_mockRMN), address(s_sourceRouter) ); + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]); + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(s_destTokens[0]), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - s_maliciousTokenPool.applyChainUpdates(chainUpdates); + s_maliciousTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); Internal.PoolUpdate[] memory removes = new Internal.PoolUpdate[](1); diff --git a/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol b/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol index 5b6b367984..a2166d36d5 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol @@ -15,9 +15,10 @@ contract ReentrantMaliciousTokenPool is TokenPool { constructor( address facade, IERC20 token, + uint8 localTokenDecimals, address rmnProxy, address router - ) TokenPool(token, new address[](0), rmnProxy, router) { + ) TokenPool(token, localTokenDecimals, new address[](0), rmnProxy, router) { i_facade = facade; } @@ -26,15 +27,20 @@ contract ReentrantMaliciousTokenPool is TokenPool { Pool.LockOrBurnInV1 calldata lockOrBurnIn ) external override returns (Pool.LockOrBurnOutV1 memory) { if (s_attacked) { - return - Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: _encodeLocalDecimals() + }); } s_attacked = true; FacadeClient(i_facade).send(lockOrBurnIn.amount); emit Burned(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: _encodeLocalDecimals() + }); } function releaseOrMint( diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol index 48bfa668df..14da65a32e 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol @@ -43,7 +43,9 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { for (uint256 i = 0; i < s_sourceTokens.length; ++i) { address token = s_sourceTokens[i]; address pool = address( - new LockReleaseTokenPool(IERC20(token), new address[](0), address(s_mockRMN), true, address(s_sourceRouter2)) + new LockReleaseTokenPool( + IERC20(token), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, address(s_sourceRouter2) + ) ); s_sourcePoolByDestPool[s_destPoolBySourceToken[token]] = pool; diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol index f1a00be78c..eeab674b95 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -421,7 +421,7 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { return Internal.EVM2AnyTokenTransfer({ sourcePoolAddress: tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool, destTokenAddress: abi.encode(destToken), - extraData: "", + extraData: abi.encode(DEFAULT_TOKEN_DECIMALS), amount: tokenAmount.amount, destExecData: abi.encode(expectedDestGasAmount) }); diff --git a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol index a3273ffdbd..9def768814 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; @@ -13,10 +13,11 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { constructor( IBurnMintERC20 token, + uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) BurnMintTokenPool(token, allowlist, rmnProxy, router) {} + ) BurnMintTokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} function setShouldRevert( bytes calldata revertReason @@ -52,7 +53,7 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { emit Burned(msg.sender, lockOrBurnIn.amount); return Pool.LockOrBurnOutV1({ destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), - destPoolData: s_sourceTokenData + destPoolData: s_sourceTokenData.length == 0 ? _encodeLocalDecimals() : s_sourceTokenData }); } @@ -68,7 +69,11 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { revert(add(32, revertReason), mload(revertReason)) } } - uint256 amount = releaseOrMintIn.amount * s_releaseOrMintMultiplier; + // Calculate the local amount + uint256 localAmount = + _calculateLocalAmount(releaseOrMintIn.amount, _parseRemoteDecimals(releaseOrMintIn.sourcePoolData)); + + uint256 amount = localAmount * s_releaseOrMintMultiplier; IBurnMintERC20(address(i_token)).mint(releaseOrMintIn.receiver, amount); emit Minted(msg.sender, releaseOrMintIn.receiver, amount); diff --git a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol index 75f6b1b85d..c067b220fc 100644 --- a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol @@ -5,27 +5,49 @@ import {Pool} from "../../libraries/Pool.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; contract TokenPoolHelper is TokenPool { + using EnumerableSet for EnumerableSet.Bytes32Set; + constructor( IERC20 token, + uint8 localTokenDecimals, address[] memory allowlist, address rmnProxy, address router - ) TokenPool(token, allowlist, rmnProxy, router) {} + ) TokenPool(token, localTokenDecimals, allowlist, rmnProxy, router) {} function lockOrBurn( Pool.LockOrBurnInV1 calldata lockOrBurnIn - ) external view override returns (Pool.LockOrBurnOutV1 memory) { + ) external override returns (Pool.LockOrBurnOutV1 memory) { + _validateLockOrBurn(lockOrBurnIn); + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } function releaseOrMint( Pool.ReleaseOrMintInV1 calldata releaseOrMintIn - ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { + ) external override returns (Pool.ReleaseOrMintOutV1 memory) { + _validateReleaseOrMint(releaseOrMintIn); + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } + function encodeLocalDecimals() external view returns (bytes memory) { + return _encodeLocalDecimals(); + } + + function parseRemoteDecimals( + bytes memory sourcePoolData + ) external view returns (uint256) { + return _parseRemoteDecimals(sourcePoolData); + } + + function calculateLocalAmount(uint256 remoteAmount, uint8 remoteDecimals) external view returns (uint256) { + return _calculateLocalAmount(remoteAmount, remoteDecimals); + } + function onlyOnRampModifier( uint64 remoteChainSelector ) external view { diff --git a/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol b/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol deleted file mode 100644 index ad41c76326..0000000000 --- a/contracts/src/v0.8/ccip/test/legacy/TokenPoolAndProxy.t.sol +++ /dev/null @@ -1,677 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {IPoolPriorTo1_5} from "../../interfaces/IPoolPriorTo1_5.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {Client} from "../../libraries/Client.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnMintTokenPoolAndProxy} from "../../pools/BurnMintTokenPoolAndProxy.sol"; -import {BurnWithFromMintTokenPoolAndProxy} from "../../pools/BurnWithFromMintTokenPoolAndProxy.sol"; -import {LockReleaseTokenPoolAndProxy} from "../../pools/LockReleaseTokenPoolAndProxy.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {EVM2EVMOnRampSetup} from "../onRamp/EVM2EVMOnRampSetup.t.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; -import {BurnMintTokenPool1_2, TokenPool1_2} from "./BurnMintTokenPool1_2.sol"; -import {BurnMintTokenPool1_4, TokenPool1_4} from "./BurnMintTokenPool1_4.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; - -contract TokenPoolAndProxyMigration is EVM2EVMOnRampSetup { - BurnMintTokenPoolAndProxy internal s_newPool; - IPoolPriorTo1_5 internal s_legacyPool; - BurnMintERC677 internal s_token; - - address internal s_offRamp; - address internal s_sourcePool = makeAddr("source_pool"); - address internal s_sourceToken = makeAddr("source_token"); - uint256 internal constant AMOUNT = 1; - - function setUp() public virtual override { - super.setUp(); - // Create a system with a token and a legacy pool - s_token = new BurnMintERC677("Test", "TEST", 18, type(uint256).max); - // dealing doesn't update the total supply, meaning the first time we burn a token we underflow, which isn't - // guarded against. Then, when we mint a token, we overflow, which is guarded against and will revert. - s_token.grantMintAndBurnRoles(OWNER); - s_token.mint(OWNER, 1e18); - - s_offRamp = s_offRamps[0]; - // Approve enough for a few calls - s_token.approve(address(s_sourceRouter), AMOUNT * 100); - - // Approve infinite fee tokens - IERC20(s_sourceFeeToken).approve(address(s_sourceRouter), type(uint256).max); - } - - /// @notice This test covers the entire migration plan for 1.0-1.2 pools to 1.5 pools. For simplicity - /// we will refer to the 1.0/1.2 pools as 1.2 pools, as they are functionally the same. - function test_tokenPoolMigration_Success_1_2() public { - // ================================================================ - // | 1 1.2 prior to upgrade | - // ================================================================ - _deployPool1_2(); - - // Ensure everything works on the 1.2 pool - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 2 Deploy self serve | - // ================================================================ - _deploySelfServe(); - - // This doesn't impact the 1.2 pool, so it should still be functional - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 3 Configure new pool on old pool | - // ================================================================ - // In the 1.2 case, everything keeps working on both the 1.2 and 1.5 pools. This config can be - // done in advance of the actual swap to 1.5 lanes. - vm.startPrank(OWNER); - TokenPool1_2.RampUpdate[] memory rampUpdates = new TokenPool1_2.RampUpdate[](1); - rampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_newPool), - allowed: true, - // The rate limits should be turned off for this fake ramp, as the 1.5 pool will handle all the - // rate limiting for us. - rateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - // Since this call doesn't impact the usability of the old pool, we can do it whenever we want - BurnMintTokenPool1_2(address(s_legacyPool)).applyRampUpdates(rampUpdates, rampUpdates); - - // Assert the 1.2 lanes still work - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 4 Update the router with to 1.5 | - // ================================================================ - - // This will stop any new messages entering the old lanes, and will direct all traffic to the - // new 1.5 lanes, and therefore to the 1.5 pools. Note that the old pools will still receive - // inflight messages, and will need to continue functioning until all of those are processed. - _fakeReleaseOrMintFromOffRamp_OLD(); - - // Everything is configured, we can now send a ccip tx to the new pool - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // ================================================================ - // | 5 Migrate to using 1.5 the pool | - // ================================================================ - // Turn off the legacy pool, this enabled the 1.5 pool logic. This should be done AFTER the new pool - // has gotten permissions to mint/burn. We see the case where that isn't done below. - vm.startPrank(OWNER); - s_newPool.setPreviousPool(IPoolPriorTo1_5(address(0))); - - // The new pool is now active, but is has not been given permissions to burn/mint yet - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, address(s_newPool))); - _ccipSend1_5(); - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, address(s_newPool))); - _fakeReleaseOrMintFromOffRamp1_5(); - - // When we do give burn/mint, the new pool is fully active - vm.startPrank(OWNER); - s_token.grantMintAndBurnRoles(address(s_newPool)); - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // Even after the pool has taken over as primary, the old pool can still process messages from the old lane - _fakeReleaseOrMintFromOffRamp_OLD(); - } - - function test_tokenPoolMigration_Success_1_4() public { - // ================================================================ - // | 1 1.4 prior to upgrade | - // ================================================================ - _deployPool1_4(); - - // Ensure everything works on the 1.4 pool - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 2 Deploy self serve | - // ================================================================ - _deploySelfServe(); - - // This doesn't impact the 1.4 pool, so it should still be functional - _ccipSend_OLD(); - _fakeReleaseOrMintFromOffRamp_OLD(); - - // ================================================================ - // | 3 Configure new pool on old pool | - // | AND | - // | Update the router with to 1.5 | - // ================================================================ - // NOTE: when this call is made, the SENDING SIDE of old lanes stop working. - vm.startPrank(OWNER); - BurnMintTokenPool1_4(address(s_legacyPool)).setRouter(address(s_newPool)); - - // This will stop any new messages entering the old lanes, and will direct all traffic to the - // new 1.5 lanes, and therefore to the 1.5 pools. Note that the old pools will still receive - // inflight messages, and will need to continue functioning until all of those are processed. - _fakeReleaseOrMintFromOffRamp_OLD(); - - // Sending to the old 1.4 pool no longer works - _ccipSend_OLD_Reverts(); - - // Everything is configured, we can now send a ccip tx - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // ================================================================ - // | 4 Migrate to using 1.5 the pool | - // ================================================================ - // Turn off the legacy pool, this enabled the 1.5 pool logic. This should be done AFTER the new pool - // has gotten permissions to mint/burn. We see the case where that isn't done below. - vm.startPrank(OWNER); - s_newPool.setPreviousPool(IPoolPriorTo1_5(address(0))); - - // The new pool is now active, but is has not been given permissions to burn/mint yet - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotBurner.selector, address(s_newPool))); - _ccipSend1_5(); - vm.expectRevert(abi.encodeWithSelector(BurnMintERC677.SenderNotMinter.selector, address(s_newPool))); - _fakeReleaseOrMintFromOffRamp1_5(); - - // When we do give burn/mint, the new pool is fully active - vm.startPrank(OWNER); - s_token.grantMintAndBurnRoles(address(s_newPool)); - _ccipSend1_5(); - _fakeReleaseOrMintFromOffRamp1_5(); - - // Even after the pool has taken over as primary, the old pool can still process messages from the old lane - _fakeReleaseOrMintFromOffRamp_OLD(); - } - - function _ccipSend_OLD() internal { - // We send the funds to the pool manually, as the ramp normally does that - deal(address(s_token), address(s_legacyPool), AMOUNT); - vm.startPrank(address(s_onRamp)); - s_legacyPool.lockOrBurn(OWNER, abi.encode(OWNER), AMOUNT, DEST_CHAIN_SELECTOR, ""); - } - - function _ccipSend_OLD_Reverts() internal { - // We send the funds to the pool manually, as the ramp normally does that - deal(address(s_token), address(s_legacyPool), AMOUNT); - vm.startPrank(address(s_onRamp)); - - vm.expectRevert(abi.encodeWithSelector(TokenPool1_4.CallerIsNotARampOnRouter.selector, address(s_onRamp))); - - s_legacyPool.lockOrBurn(OWNER, abi.encode(OWNER), AMOUNT, DEST_CHAIN_SELECTOR, ""); - } - - function _ccipSend1_5() internal { - vm.startPrank(address(OWNER)); - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: address(s_token), amount: AMOUNT}); - - s_sourceRouter.ccipSend( - DEST_CHAIN_SELECTOR, - Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: "" - }) - ); - } - - function _fakeReleaseOrMintFromOffRamp1_5() internal { - // This is a fake call to simulate the release or mint from the "offRamp" - vm.startPrank(s_offRamp); - s_newPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - receiver: OWNER, - amount: AMOUNT, - localToken: address(s_token), - sourcePoolAddress: abi.encode(s_sourcePool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function _fakeReleaseOrMintFromOffRamp_OLD() internal { - // This is a fake call to simulate the release or mint from the "offRamp" - vm.startPrank(s_offRamp); - s_legacyPool.releaseOrMint(abi.encode(OWNER), OWNER, AMOUNT, SOURCE_CHAIN_SELECTOR, ""); - } - - function _deployPool1_2() internal { - vm.startPrank(OWNER); - s_legacyPool = new BurnMintTokenPool1_2(s_token, new address[](0), address(s_mockRMN)); - s_token.grantMintAndBurnRoles(address(s_legacyPool)); - - TokenPool1_2.RampUpdate[] memory onRampUpdates = new TokenPool1_2.RampUpdate[](1); - onRampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_onRamp), - allowed: true, - rateLimiterConfig: _getInboundRateLimiterConfig() - }); - TokenPool1_2.RampUpdate[] memory offRampUpdates = new TokenPool1_2.RampUpdate[](1); - offRampUpdates[0] = TokenPool1_2.RampUpdate({ - ramp: address(s_offRamp), - allowed: true, - rateLimiterConfig: _getInboundRateLimiterConfig() - }); - BurnMintTokenPool1_2(address(s_legacyPool)).applyRampUpdates(onRampUpdates, offRampUpdates); - } - - function _deployPool1_4() internal { - vm.startPrank(OWNER); - s_legacyPool = new BurnMintTokenPool1_4(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_token.grantMintAndBurnRoles(address(s_legacyPool)); - - TokenPool1_4.ChainUpdate[] memory legacyChainUpdates = new TokenPool1_4.ChainUpdate[](2); - legacyChainUpdates[0] = TokenPool1_4.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - legacyChainUpdates[1] = TokenPool1_4.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - BurnMintTokenPool1_4(address(s_legacyPool)).applyChainUpdates(legacyChainUpdates); - } - - function _deploySelfServe() internal { - vm.startPrank(OWNER); - // Deploy the new pool - s_newPool = new BurnMintTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - // Set the previous pool on the new pool - s_newPool.setPreviousPool(s_legacyPool); - - // Configure the lanes just like the legacy pool - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_sourcePool), - remoteTokenAddress: abi.encode(s_sourceToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_newPool.applyChainUpdates(chainUpdates); - - // Register the token on the token admin registry - s_tokenAdminRegistry.proposeAdministrator(address(s_token), OWNER); - // Accept ownership of the token - s_tokenAdminRegistry.acceptAdminRole(address(s_token)); - // Set the pool on the admin registry - s_tokenAdminRegistry.setPool(address(s_token), address(s_newPool)); - } -} - -contract TokenPoolAndProxy is EVM2EVMOnRampSetup { - event Burned(address indexed sender, uint256 amount); - event Minted(address indexed sender, address indexed recipient, uint256 amount); - - IPoolV1 internal s_pool; - BurnMintERC677 internal s_token; - IPoolPriorTo1_5 internal s_legacyPool; - address internal s_fakeOffRamp = makeAddr("off_ramp"); - - address internal s_destPool = makeAddr("dest_pool"); - - function setUp() public virtual override { - super.setUp(); - s_token = BurnMintERC677(s_sourceFeeToken); - - Router.OffRamp[] memory fakeOffRamps = new Router.OffRamp[](1); - fakeOffRamps[0] = Router.OffRamp({sourceChainSelector: DEST_CHAIN_SELECTOR, offRamp: s_fakeOffRamp}); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), fakeOffRamps); - - s_token.grantMintAndBurnRoles(OWNER); - s_token.mint(OWNER, 1e18); - } - - function test_lockOrBurn_burnMint_Success() public { - s_pool = new BurnMintTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - _configurePool(); - _deployOldPool(); - _assertLockOrBurnCorrect(); - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(IPoolPriorTo1_5(address(0))); - - _assertReleaseOrMintCorrect(); - } - - function test_lockOrBurn_burnWithFromMint_Success() public { - s_pool = - new BurnWithFromMintTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - _configurePool(); - _deployOldPool(); - _assertLockOrBurnCorrect(); - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(IPoolPriorTo1_5(address(0))); - - _assertReleaseOrMintCorrect(); - } - - function test_lockOrBurn_lockRelease_Success() public { - s_pool = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - _configurePool(); - _deployOldPool(); - _assertLockOrBurnCorrect(); - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(IPoolPriorTo1_5(address(0))); - - _assertReleaseOrMintCorrect(); - } - - function _deployOldPool() internal { - s_legacyPool = new BurnMintTokenPool1_2(s_token, new address[](0), address(s_mockRMN)); - s_token.grantMintAndBurnRoles(address(s_legacyPool)); - - TokenPool1_2.RampUpdate[] memory onRampUpdates = new TokenPool1_2.RampUpdate[](1); - onRampUpdates[0] = - TokenPool1_2.RampUpdate({ramp: address(s_pool), allowed: true, rateLimiterConfig: _getInboundRateLimiterConfig()}); - TokenPool1_2.RampUpdate[] memory offRampUpdates = new TokenPool1_2.RampUpdate[](1); - offRampUpdates[0] = - TokenPool1_2.RampUpdate({ramp: address(s_pool), allowed: true, rateLimiterConfig: _getInboundRateLimiterConfig()}); - BurnMintTokenPool1_2(address(s_legacyPool)).applyRampUpdates(onRampUpdates, offRampUpdates); - } - - function _configurePool() internal { - TokenPool.ChainUpdate[] memory chains = new TokenPool.ChainUpdate[](1); - chains[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - BurnMintTokenPoolAndProxy(address(s_pool)).applyChainUpdates(chains); - - // CCIP Token Admin has already been registered from TokenSetup - s_tokenAdminRegistry.setPool(address(s_token), address(s_pool)); - - s_token.grantMintAndBurnRoles(address(s_pool)); - } - - function _assertLockOrBurnCorrect() internal { - uint256 amount = 1234; - vm.startPrank(address(s_onRamp)); - - // lockOrBurn, assert normal path is taken - deal(address(s_token), address(s_pool), amount); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: abi.encode(OWNER), - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: OWNER, - amount: amount, - localToken: address(s_token) - }) - ); - - // set legacy pool - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(s_legacyPool); - - // lockOrBurn, assert legacy pool is called - - vm.startPrank(address(s_onRamp)); - deal(address(s_token), address(s_pool), amount); - - vm.expectEmit(address(s_legacyPool)); - emit Burned(address(s_pool), amount); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: abi.encode(OWNER), - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: OWNER, - amount: amount, - localToken: address(s_token) - }) - ); - } - - function _assertReleaseOrMintCorrect() internal { - uint256 amount = 1234; - vm.startPrank(s_fakeOffRamp); - - // releaseOrMint, assert normal path is taken - deal(address(s_token), address(s_pool), amount); - - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - receiver: OWNER, - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: abi.encode(OWNER), - amount: amount, - localToken: address(s_token), - sourcePoolAddress: abi.encode(s_destPool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - - // set legacy pool - - vm.startPrank(OWNER); - BurnMintTokenPoolAndProxy(address(s_pool)).setPreviousPool(s_legacyPool); - - // releaseOrMint, assert legacy pool is called - - vm.startPrank(address(s_fakeOffRamp)); - - vm.expectEmit(address(s_legacyPool)); - emit Minted(address(s_pool), address(OWNER), amount); - - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - receiver: OWNER, - remoteChainSelector: DEST_CHAIN_SELECTOR, - originalSender: abi.encode(OWNER), - amount: amount, - localToken: address(s_token), - sourcePoolAddress: abi.encode(s_destPool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_setPreviousPool_Success() public { - LockReleaseTokenPoolAndProxy pool = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - - assertEq(pool.getPreviousPool(), address(0)); - - address newLegacyPool = makeAddr("new_legacy_pool"); - - vm.startPrank(OWNER); - pool.setPreviousPool(IPoolPriorTo1_5(newLegacyPool)); - assertEq(pool.getPreviousPool(), address(newLegacyPool)); - } -} - -//// -/// Duplicated tests from LockReleaseTokenPool.t.sol -/// - -contract LockReleaseTokenPoolAndProxySetup is RouterSetup { - IERC20 internal s_token; - LockReleaseTokenPoolAndProxy internal s_lockReleaseTokenPoolAndProxy; - LockReleaseTokenPoolAndProxy internal s_lockReleaseTokenPoolAndProxyWithAllowList; - address[] internal s_allowedList; - - address internal s_allowedOnRamp = address(123); - address internal s_allowedOffRamp = address(234); - - address internal s_destPoolAddress = address(2736782345); - address internal s_sourcePoolAddress = address(53852352095); - - function setUp() public virtual override { - RouterSetup.setUp(); - s_token = new BurnMintERC677("LINK", "LNK", 18, 0); - deal(address(s_token), OWNER, type(uint256).max); - s_lockReleaseTokenPoolAndProxy = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - - s_allowedList.push(USER_1); - s_allowedList.push(DUMMY_CONTRACT_ADDRESS); - s_lockReleaseTokenPoolAndProxyWithAllowList = - new LockReleaseTokenPoolAndProxy(s_token, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter)); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolAddress), - remoteTokenAddress: abi.encode(address(s_token)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_lockReleaseTokenPoolAndProxy.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolAndProxyWithAllowList.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolAndProxy.setRebalancer(OWNER); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } -} - -contract LockReleaseTokenPoolAndProxy_setRebalancer is LockReleaseTokenPoolAndProxySetup { - function test_SetRebalancer_Success() public { - assertEq(address(s_lockReleaseTokenPoolAndProxy.getRebalancer()), OWNER); - s_lockReleaseTokenPoolAndProxy.setRebalancer(STRANGER); - assertEq(address(s_lockReleaseTokenPoolAndProxy.getRebalancer()), STRANGER); - } - - function test_SetRebalancer_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_lockReleaseTokenPoolAndProxy.setRebalancer(STRANGER); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity is LockReleaseTokenPoolAndProxySetup { - function test_CanAcceptLiquidity_Success() public { - assertEq(true, s_lockReleaseTokenPoolAndProxy.canAcceptLiquidity()); - - s_lockReleaseTokenPoolAndProxy = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - assertEq(false, s_lockReleaseTokenPoolAndProxy.canAcceptLiquidity()); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_provideLiquidity is LockReleaseTokenPoolAndProxySetup { - function test_Fuzz_ProvideLiquidity_Success( - uint256 amount - ) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPoolAndProxy), amount); - - s_lockReleaseTokenPoolAndProxy.provideLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre - amount); - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPoolAndProxy)), amount); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPoolAndProxy.provideLiquidity(1); - } - - function test_Fuzz_ExceedsAllowance( - uint256 amount - ) public { - vm.assume(amount > 0); - vm.expectRevert("ERC20: insufficient allowance"); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(amount); - } - - function test_LiquidityNotAccepted_Revert() public { - s_lockReleaseTokenPoolAndProxy = - new LockReleaseTokenPoolAndProxy(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - - vm.expectRevert(LockReleaseTokenPoolAndProxy.LiquidityNotAccepted.selector); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(1); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity is LockReleaseTokenPoolAndProxySetup { - function test_Fuzz_WithdrawalLiquidity_Success( - uint256 amount - ) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPoolAndProxy), amount); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(amount); - - s_lockReleaseTokenPoolAndProxy.withdrawLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPoolAndProxy.withdrawLiquidity(1); - } - - function test_InsufficientLiquidity_Revert() public { - uint256 maxUint256 = 2 ** 256 - 1; - s_token.approve(address(s_lockReleaseTokenPoolAndProxy), maxUint256); - s_lockReleaseTokenPoolAndProxy.provideLiquidity(maxUint256); - - vm.startPrank(address(s_lockReleaseTokenPoolAndProxy)); - s_token.transfer(OWNER, maxUint256); - vm.startPrank(OWNER); - - vm.expectRevert(LockReleaseTokenPoolAndProxy.InsufficientLiquidity.selector); - s_lockReleaseTokenPoolAndProxy.withdrawLiquidity(1); - } -} - -contract LockReleaseTokenPoolPoolAndProxy_supportsInterface is LockReleaseTokenPoolAndProxySetup { - function test_SupportsInterface_Success() public view { - assertTrue(s_lockReleaseTokenPoolAndProxy.supportsInterface(type(IPoolV1).interfaceId)); - assertTrue(s_lockReleaseTokenPoolAndProxy.supportsInterface(type(IERC165).interfaceId)); - } -} diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol index 40309a8da6..07f3f459ce 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol @@ -14,6 +14,9 @@ import {TokenPool} from "../../pools/TokenPool.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; import "./EVM2EVMOnRampSetup.t.sol"; +import {IERC20Metadata} from + "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + contract EVM2EVMOnRamp_constructor is EVM2EVMOnRampSetup { function test_Constructor_Success() public { EVM2EVMOnRamp.StaticConfig memory staticConfig = EVM2EVMOnRamp.StaticConfig({ @@ -571,7 +574,7 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { Internal.SourceTokenData({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[changedToken]), destTokenAddress: abi.encode(s_destTokenBySourceToken[changedToken]), - extraData: "", + extraData: abi.encode(DEFAULT_TOKEN_DECIMALS), // The user will be billed either the default or the override, so we send the exact amount that we billed for // to the destination chain to be used for the token releaseOrMint and transfer. destGasAmount: tokenTransferFeeConfigArgs[0].destGasOverhead @@ -772,7 +775,7 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { vm.startPrank(OWNER); MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC677(sourceETH), new address[](0), address(s_mockRMN), address(s_sourceRouter) + BurnMintERC677(sourceETH), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) ); BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); deal(address(sourceETH), address(newPool), type(uint256).max); @@ -780,17 +783,19 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { // Add TokenPool to OnRamp s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_destTokenPool); + // Allow chain in TokenPool TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(s_destToken), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - newPool.applyChainUpdates(chainUpdates); + newPool.applyChainUpdates(new uint64[](0), chainUpdates); Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); @@ -997,34 +1002,47 @@ contract EVM2EVMOnRamp_getFeeSetup is EVM2EVMOnRampSetup { s_tokenAdminRegistry.acceptAdminRole(CUSTOM_TOKEN); LockReleaseTokenPool wrappedNativePool = new LockReleaseTokenPool( - IERC20(s_sourceRouter.getWrappedNative()), new address[](0), address(s_mockRMN), true, address(s_sourceRouter) + IERC20(s_sourceRouter.getWrappedNative()), + DEFAULT_TOKEN_DECIMALS, + new address[](0), + address(s_mockRMN), + true, + address(s_sourceRouter) ); + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(address(111111)); + TokenPool.ChainUpdate[] memory wrappedNativeChainUpdate = new TokenPool.ChainUpdate[](1); wrappedNativeChainUpdate[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(address(111111)), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(s_destToken), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - wrappedNativePool.applyChainUpdates(wrappedNativeChainUpdate); + wrappedNativePool.applyChainUpdates(new uint64[](0), wrappedNativeChainUpdate); s_tokenAdminRegistry.setPool(s_sourceRouter.getWrappedNative(), address(wrappedNativePool)); + vm.mockCall( + CUSTOM_TOKEN, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(DEFAULT_TOKEN_DECIMALS) + ); + LockReleaseTokenPool customPool = new LockReleaseTokenPool( - IERC20(CUSTOM_TOKEN), new address[](0), address(s_mockRMN), true, address(s_sourceRouter) + IERC20(CUSTOM_TOKEN), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, address(s_sourceRouter) ); + + remotePoolAddresses[0] = abi.encode(makeAddr("random")); + TokenPool.ChainUpdate[] memory customChainUpdate = new TokenPool.ChainUpdate[](1); customChainUpdate[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(makeAddr("random")), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(s_destToken), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - customPool.applyChainUpdates(customChainUpdate); + customPool.applyChainUpdates(new uint64[](0), customChainUpdate); s_tokenAdminRegistry.setPool(CUSTOM_TOKEN, address(customPool)); s_feeTokenPrice = s_sourceTokenPrices[0]; diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol index 84350448a1..ead48ed98e 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol @@ -223,7 +223,7 @@ contract EVM2EVMOnRampSetup is TokenSetup, FeeQuoterSetup { Internal.SourceTokenData({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[message.tokenAmounts[i].token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[message.tokenAmounts[i].token]), - extraData: "", + extraData: abi.encode(DEFAULT_TOKEN_DECIMALS), destGasAmount: tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : DEFAULT_TOKEN_DEST_GAS_OVERHEAD diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index 5ccd20b015..fdd6130e3d 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -531,7 +531,11 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.startPrank(OWNER); MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC677(sourceETH), new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) + BurnMintERC677(sourceETH), + DEFAULT_TOKEN_DECIMALS, + new address[](0), + address(s_mockRMNRemote), + address(s_sourceRouter) ); BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); deal(address(sourceETH), address(newPool), type(uint256).max); @@ -539,17 +543,19 @@ contract OnRamp_forwardFromRouter is OnRampSetup { // Add TokenPool to OnRamp s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_destTokenPool); + // Allow chain in TokenPool TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); chainUpdates[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(s_destToken), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - newPool.applyChainUpdates(chainUpdates); + newPool.applyChainUpdates(new uint64[](0), chainUpdates); Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol similarity index 53% rename from contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol rename to contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol index b5967e74d1..44a8f2299a 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPool.lockOrBurn.t.sol @@ -1,41 +1,27 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnFromMintTokenPool} from "../../pools/BurnFromMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {BurnMintSetup} from "./BurnMintSetup.t.sol"; +import {Pool} from "../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BurnFromMintTokenPoolSetup} from "./BurnFromMintTokenPoolSetup.t.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract BurnFromMintTokenPoolSetup is BurnMintSetup { - BurnFromMintTokenPool internal s_pool; - - function setUp() public virtual override { - BurnMintSetup.setUp(); - - s_pool = new BurnFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); - - _applyChainUpdates(address(s_pool)); - } -} +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { - function test_Setup_Success() public view { - assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + function test_setup_Success() public view { + assertEq(address(s_burnMintERC20), address(s_pool.getToken())); assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); - assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); - assertEq("BurnFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); + assertEq(type(uint256).max, s_burnMintERC20.allowance(address(s_pool), address(s_pool))); + assertEq("BurnFromMintTokenPool 1.5.1", s_pool.typeAndVersion()); } function test_PoolBurn_Success() public { uint256 burnAmount = 20_000e18; - deal(address(s_burnMintERC677), address(s_pool), burnAmount); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); + deal(address(s_burnMintERC20), address(s_pool), burnAmount); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); vm.startPrank(s_burnMintOnRamp); @@ -49,7 +35,7 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); bytes4 expectedSignature = bytes4(keccak256("burnFrom(address,uint256)")); - vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); + vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); s_pool.lockOrBurn( Pool.LockOrBurnInV1({ @@ -57,17 +43,17 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { receiver: bytes(""), amount: burnAmount, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) + localToken: address(s_burnMintERC20) }) ); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); } // Should not burn tokens if cursed. function test_PoolBurnRevertNotHealthy_Revert() public { s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); + uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); @@ -77,11 +63,11 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { receiver: bytes(""), amount: 1e5, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) + localToken: address(s_burnMintERC20) }) ); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); } function test_ChainNotAllowed_Revert() public { @@ -92,7 +78,7 @@ contract BurnFromMintTokenPool_lockOrBurn is BurnFromMintTokenPoolSetup { originalSender: bytes(""), receiver: OWNER, amount: 1, - localToken: address(s_burnMintERC677), + localToken: address(s_burnMintERC20), remoteChainSelector: wrongChainSelector, sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, sourcePoolData: _generateSourceTokenData().extraData, diff --git a/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol new file mode 100644 index 0000000000..98de04ea3f --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnFromMintTokenPool} from "../../../pools/BurnFromMintTokenPool.sol"; +import {BurnMintSetup} from "../BurnMintTokenPool/BurnMintSetup.t.sol"; + +contract BurnFromMintTokenPoolSetup is BurnMintSetup { + BurnFromMintTokenPool internal s_pool; + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = new BurnFromMintTokenPool( + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol deleted file mode 100644 index 8a6d047380..0000000000 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool.t.sol +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {BurnMintSetup} from "./BurnMintSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract BurnMintTokenPoolSetup is BurnMintSetup { - BurnMintTokenPool internal s_pool; - - function setUp() public virtual override { - BurnMintSetup.setUp(); - - s_pool = new BurnMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); - - _applyChainUpdates(address(s_pool)); - } -} - -contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { - function test_Setup_Success() public view { - assertEq(address(s_burnMintERC677), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); - assertEq(false, s_pool.getAllowListEnabled()); - assertEq("BurnMintTokenPool 1.5.0", s_pool.typeAndVersion()); - } - - function test_PoolBurn_Success() public { - uint256 burnAmount = 20_000e18; - - deal(address(s_burnMintERC677), address(s_pool), burnAmount); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); - - vm.startPrank(s_burnMintOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(burnAmount); - - vm.expectEmit(); - emit IERC20.Transfer(address(s_pool), address(0), burnAmount); - - vm.expectEmit(); - emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); - - bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); - vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, burnAmount)); - - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: burnAmount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); - } - - // Should not burn tokens if cursed. - function test_PoolBurnRevertNotHealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); - vm.startPrank(s_burnMintOnRamp); - - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: 1e5, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) - }) - ); - - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); - } - - function test_ChainNotAllowed_Revert() public { - uint64 wrongChainSelector = 8838833; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); - s_pool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: bytes(""), - amount: 1, - remoteChainSelector: wrongChainSelector, - localToken: address(s_burnMintERC677) - }) - ); - } -} - -contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { - function test_PoolMint_Success() public { - uint256 amount = 1e19; - address receiver = makeAddr("receiver_address"); - - vm.startPrank(s_burnMintOffRamp); - - vm.expectEmit(); - emit IERC20.Transfer(address(0), receiver, amount); - - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: receiver, - amount: amount, - localToken: address(s_burnMintERC677), - remoteChainSelector: DEST_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_remoteBurnMintPool), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - - assertEq(s_burnMintERC677.balanceOf(receiver), amount); - } - - function test_PoolMintNotHealthy_Revert() public { - // Should not mint tokens if cursed. - s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(OWNER); - vm.startPrank(s_burnMintOffRamp); - - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1e5, - localToken: address(s_burnMintERC677), - remoteChainSelector: DEST_CHAIN_SELECTOR, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - - assertEq(s_burnMintERC677.balanceOf(OWNER), before); - } - - function test_ChainNotAllowed_Revert() public { - uint64 wrongChainSelector = 8838833; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); - s_pool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1, - localToken: address(s_burnMintERC677), - remoteChainSelector: wrongChainSelector, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol similarity index 60% rename from contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol rename to contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol index 7bf0ce57d5..08c600db5a 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnMintSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintSetup.t.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {BurnMintTokenPool} from "../../pools/BurnMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; +import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; +import {Router} from "../../../Router.sol"; +import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {RouterSetup} from "../../router/RouterSetup.t.sol"; contract BurnMintSetup is RouterSetup { - BurnMintERC677 internal s_burnMintERC677; + BurnMintERC20 internal s_burnMintERC20; address internal s_burnMintOffRamp = makeAddr("burn_mint_offRamp"); address internal s_burnMintOnRamp = makeAddr("burn_mint_onRamp"); @@ -18,23 +18,25 @@ contract BurnMintSetup is RouterSetup { function setUp() public virtual override { RouterSetup.setUp(); - s_burnMintERC677 = new BurnMintERC677("Chainlink Token", "LINK", 18, 0); + s_burnMintERC20 = new BurnMintERC20("Chainlink Token", "LINK", 18, 0, 0); } function _applyChainUpdates( address pool ) internal { - TokenPool.ChainUpdate[] memory chains = new TokenPool.ChainUpdate[](1); - chains[0] = TokenPool.ChainUpdate({ + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_remoteBurnMintPool); + + TokenPool.ChainUpdate[] memory chainsToAdd = new TokenPool.ChainUpdate[](1); + chainsToAdd[0] = TokenPool.ChainUpdate({ remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_remoteBurnMintPool), + remotePoolAddresses: remotePoolAddresses, remoteTokenAddress: abi.encode(s_remoteToken), - allowed: true, outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), inboundRateLimiterConfig: _getInboundRateLimiterConfig() }); - BurnMintTokenPool(pool).applyChainUpdates(chains); + BurnMintTokenPool(pool).applyChainUpdates(new uint64[](0), chainsToAdd); Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_burnMintOnRamp}); diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol new file mode 100644 index 0000000000..e0bbffa991 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BurnMintSetup} from "./BurnMintSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract BurnMintTokenPoolSetup is BurnMintSetup { + BurnMintTokenPool internal s_pool; + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = new BurnMintTokenPool( + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} + +contract BurnMintTokenPool_lockOrBurn is BurnMintTokenPoolSetup { + function test_Setup_Success() public view { + assertEq(address(s_burnMintERC20), address(s_pool.getToken())); + assertEq(address(s_mockRMN), s_pool.getRmnProxy()); + assertEq(false, s_pool.getAllowListEnabled()); + assertEq("BurnMintTokenPool 1.5.1", s_pool.typeAndVersion()); + } + + function test_PoolBurn_Success() public { + uint256 burnAmount = 20_000e18; + + deal(address(s_burnMintERC20), address(s_pool), burnAmount); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); + + vm.startPrank(s_burnMintOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(burnAmount); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_pool), address(0), burnAmount); + + vm.expectEmit(); + emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); + + bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); + vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, burnAmount)); + + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: burnAmount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC20) + }) + ); + + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); + } + + // Should not burn tokens if cursed. + function test_PoolBurnRevertNotHealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); + vm.startPrank(s_burnMintOnRamp); + + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: 1e5, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC20) + }) + ); + + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); + } + + function test_ChainNotAllowed_Revert() public { + uint64 wrongChainSelector = 8838833; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); + s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: 1, + remoteChainSelector: wrongChainSelector, + localToken: address(s_burnMintERC20) + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol new file mode 100644 index 0000000000..e950b07988 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {BurnMintTokenPool} from "../../../pools/BurnMintTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BurnMintSetup} from "./BurnMintSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract BurnMintTokenPoolSetup is BurnMintSetup { + BurnMintTokenPool internal s_pool; + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = new BurnMintTokenPool( + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} + +contract BurnMintTokenPool_releaseOrMint is BurnMintTokenPoolSetup { + function test_PoolMint_Success() public { + uint256 amount = 1e19; + address receiver = makeAddr("receiver_address"); + + vm.startPrank(s_burnMintOffRamp); + + vm.expectEmit(); + emit IERC20.Transfer(address(0), receiver, amount); + + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: receiver, + amount: amount, + localToken: address(s_burnMintERC20), + remoteChainSelector: DEST_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_remoteBurnMintPool), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + + assertEq(s_burnMintERC20.balanceOf(receiver), amount); + } + + function test_PoolMintNotHealthy_Revert() public { + // Should not mint tokens if cursed. + s_mockRMN.setGlobalCursed(true); + uint256 before = s_burnMintERC20.balanceOf(OWNER); + vm.startPrank(s_burnMintOffRamp); + + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1e5, + localToken: address(s_burnMintERC20), + remoteChainSelector: DEST_CHAIN_SELECTOR, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + + assertEq(s_burnMintERC20.balanceOf(OWNER), before); + } + + function test_ChainNotAllowed_Revert() public { + uint64 wrongChainSelector = 8838833; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, wrongChainSelector)); + s_pool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1, + localToken: address(s_burnMintERC20), + remoteChainSelector: wrongChainSelector, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol new file mode 100644 index 0000000000..bb58afd254 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPool.lockOrBurn.t.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BurnMintWithLockReleaseFlagTokenPool} from "../../../pools/USDC/BurnMintWithLockReleaseFlagTokenPool.sol"; + +import {LOCK_RELEASE_FLAG} from "../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {BurnMintSetup} from "../BurnMintTokenPool/BurnMintSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract BurnMintWithLockReleaseFlagTokenPoolSetup is BurnMintSetup { + BurnMintWithLockReleaseFlagTokenPool internal s_pool; + + function setUp() public virtual override { + BurnMintSetup.setUp(); + + s_pool = new BurnMintWithLockReleaseFlagTokenPool( + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); + + _applyChainUpdates(address(s_pool)); + } +} + +contract BurnMintWithLockReleaseFlagTokenPool_lockOrBurn is BurnMintWithLockReleaseFlagTokenPoolSetup { + function test_LockOrBurn_CorrectReturnData_Success() public { + uint256 burnAmount = 20_000e18; + + deal(address(s_burnMintERC20), address(s_pool), burnAmount); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); + + vm.startPrank(s_burnMintOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(burnAmount); + + vm.expectEmit(); + emit IERC20.Transfer(address(s_pool), address(0), burnAmount); + + vm.expectEmit(); + emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); + + bytes4 expectedSignature = bytes4(keccak256("burn(uint256)")); + vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, burnAmount)); + + Pool.LockOrBurnOutV1 memory lockOrBurnOut = s_pool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: bytes(""), + amount: burnAmount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_burnMintERC20) + }) + ); + + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); + + assertEq(bytes4(lockOrBurnOut.destPoolData), LOCK_RELEASE_FLAG); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintRebasingTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintRebasingTokenPool.t.sol deleted file mode 100644 index ea5b4a2c43..0000000000 --- a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintRebasingTokenPool.t.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; - -import {Pool} from "../../libraries/Pool.sol"; -import {BurnWithFromMintRebasingTokenPool} from "../../pools/BurnWithFromMintRebasingTokenPool.sol"; -import {BurnMintSetup} from "./BurnMintSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {ERC20RebasingHelper} from "../helpers/ERC20RebasingHelper.sol"; - -contract BurnWithFromMintRebasingTokenPoolSetup is BurnMintSetup { - BurnWithFromMintRebasingTokenPool internal s_pool; - ERC20RebasingHelper internal s_rebasingToken; - - function setUp() public virtual override { - BurnMintSetup.setUp(); - - s_rebasingToken = new ERC20RebasingHelper(); - - s_pool = new BurnWithFromMintRebasingTokenPool( - IBurnMintERC20(address(s_rebasingToken)), new address[](0), address(s_mockRMN), address(s_sourceRouter) - ); - - _applyChainUpdates(address(s_pool)); - - deal(address(s_rebasingToken), OWNER, 1e18); - - vm.startPrank(s_burnMintOffRamp); - } -} - -contract BurnWithFromMintTokenPool_releaseOrMint is BurnWithFromMintRebasingTokenPoolSetup { - function test_Setup_Success() public view { - assertEq(address(s_rebasingToken), address(s_pool.getToken())); - assertEq(address(s_mockRMN), s_pool.getRmnProxy()); - assertEq(false, s_pool.getAllowListEnabled()); - assertEq(type(uint256).max, s_rebasingToken.allowance(address(s_pool), address(s_pool))); - assertEq("BurnWithFromMintRebasingTokenPool 1.5.0", s_pool.typeAndVersion()); - } - - function test_releaseOrMint_Success() public { - uint256 amount = 1000; - uint256 balancePre = s_rebasingToken.balanceOf(address(OWNER)); - - Pool.ReleaseOrMintOutV1 memory releaseOrMintOut = s_pool.releaseOrMint(_getReleaseOrMintIn(amount)); - - assertEq(amount, releaseOrMintOut.destinationAmount); - assertEq(balancePre + amount, s_rebasingToken.balanceOf(address(OWNER))); - } - - function testFuzz_releaseOrMint_rebasing_success( - uint16 multiplierPercentage - ) public { - uint256 amount = 1000; - uint256 expectedAmount = amount * multiplierPercentage / 100; - s_rebasingToken.setMultiplierPercentage(multiplierPercentage); - - uint256 balancePre = s_rebasingToken.balanceOf(address(OWNER)); - - Pool.ReleaseOrMintOutV1 memory releaseOrMintOut = s_pool.releaseOrMint(_getReleaseOrMintIn(amount)); - - assertEq(expectedAmount, releaseOrMintOut.destinationAmount); - assertEq(balancePre + expectedAmount, s_rebasingToken.balanceOf(address(OWNER))); - } - - function test_releaseOrMint_NegativeMintAmount_reverts() public { - uint256 amount = 1000; - s_rebasingToken.setMintShouldBurn(true); - - vm.expectRevert(abi.encodeWithSelector(BurnWithFromMintRebasingTokenPool.NegativeMintAmount.selector, amount)); - - s_pool.releaseOrMint(_getReleaseOrMintIn(amount)); - } - - function _getReleaseOrMintIn( - uint256 amount - ) internal view returns (Pool.ReleaseOrMintInV1 memory) { - return Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: amount, - localToken: address(s_rebasingToken), - remoteChainSelector: DEST_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_remoteBurnMintPool), - sourcePoolData: "", - offchainTokenData: "" - }); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol similarity index 60% rename from contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol rename to contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol index 92e871708d..b96dcd78b5 100644 --- a/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {BurnWithFromMintTokenPool} from "../../pools/BurnWithFromMintTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {BurnMintSetup} from "./BurnMintSetup.t.sol"; +import {Pool} from "../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {BurnWithFromMintTokenPool} from "../../../pools/BurnWithFromMintTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {BurnMintSetup} from "../BurnMintTokenPool/BurnMintSetup.t.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { BurnWithFromMintTokenPool internal s_pool; @@ -15,9 +15,10 @@ contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { function setUp() public virtual override { BurnMintSetup.setUp(); - s_pool = - new BurnWithFromMintTokenPool(s_burnMintERC677, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - s_burnMintERC677.grantMintAndBurnRoles(address(s_pool)); + s_pool = new BurnWithFromMintTokenPool( + s_burnMintERC20, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + s_burnMintERC20.grantMintAndBurnRoles(address(s_pool)); _applyChainUpdates(address(s_pool)); } @@ -25,18 +26,18 @@ contract BurnWithFromMintTokenPoolSetup is BurnMintSetup { contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup { function test_Setup_Success() public view { - assertEq(address(s_burnMintERC677), address(s_pool.getToken())); + assertEq(address(s_burnMintERC20), address(s_pool.getToken())); assertEq(address(s_mockRMN), s_pool.getRmnProxy()); assertEq(false, s_pool.getAllowListEnabled()); - assertEq(type(uint256).max, s_burnMintERC677.allowance(address(s_pool), address(s_pool))); - assertEq("BurnWithFromMintTokenPool 1.5.0", s_pool.typeAndVersion()); + assertEq(type(uint256).max, s_burnMintERC20.allowance(address(s_pool), address(s_pool))); + assertEq("BurnWithFromMintTokenPool 1.5.1", s_pool.typeAndVersion()); } function test_PoolBurn_Success() public { uint256 burnAmount = 20_000e18; - deal(address(s_burnMintERC677), address(s_pool), burnAmount); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), burnAmount); + deal(address(s_burnMintERC20), address(s_pool), burnAmount); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), burnAmount); vm.startPrank(s_burnMintOnRamp); @@ -50,7 +51,7 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup emit TokenPool.Burned(address(s_burnMintOnRamp), burnAmount); bytes4 expectedSignature = bytes4(keccak256("burn(address,uint256)")); - vm.expectCall(address(s_burnMintERC677), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); + vm.expectCall(address(s_burnMintERC20), abi.encodeWithSelector(expectedSignature, address(s_pool), burnAmount)); s_pool.lockOrBurn( Pool.LockOrBurnInV1({ @@ -58,17 +59,17 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup receiver: bytes(""), amount: burnAmount, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) + localToken: address(s_burnMintERC20) }) ); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), 0); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), 0); } // Should not burn tokens if cursed. function test_PoolBurnRevertNotHealthy_Revert() public { s_mockRMN.setGlobalCursed(true); - uint256 before = s_burnMintERC677.balanceOf(address(s_pool)); + uint256 before = s_burnMintERC20.balanceOf(address(s_pool)); vm.startPrank(s_burnMintOnRamp); vm.expectRevert(TokenPool.CursedByRMN.selector); @@ -78,11 +79,11 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup receiver: bytes(""), amount: 1e5, remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_burnMintERC677) + localToken: address(s_burnMintERC20) }) ); - assertEq(s_burnMintERC677.balanceOf(address(s_pool)), before); + assertEq(s_burnMintERC20.balanceOf(address(s_pool)), before); } function test_ChainNotAllowed_Revert() public { @@ -93,7 +94,7 @@ contract BurnWithFromMintTokenPool_lockOrBurn is BurnWithFromMintTokenPoolSetup originalSender: bytes(""), receiver: OWNER, amount: 1, - localToken: address(s_burnMintERC677), + localToken: address(s_burnMintERC20), remoteChainSelector: wrongChainSelector, sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, sourcePoolData: _generateSourceTokenData().extraData, diff --git a/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol deleted file mode 100644 index 73426129ef..0000000000 --- a/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol +++ /dev/null @@ -1,886 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; - -import {TokenPool} from "../../pools/TokenPool.sol"; -import {HybridLockReleaseUSDCTokenPool} from "../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; -import {USDCBridgeMigrator} from "../../pools/USDC/USDCBridgeMigrator.sol"; -import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; -import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; - -contract USDCTokenPoolSetup is BaseTest { - IBurnMintERC20 internal s_token; - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; - - struct USDCMessage { - uint32 version; - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - bytes32 sender; - bytes32 recipient; - bytes32 destinationCaller; - bytes messageBody; - } - - uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; - uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; - - bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); - address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); - address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); - address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); - - address internal s_routerAllowedOnRamp = address(3456); - address internal s_routerAllowedOffRamp = address(234); - Router internal s_router; - - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; - HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; - address[] internal s_allowedList; - - function setUp() public virtual override { - BaseTest.setUp(); - BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); - s_token = usdcToken; - deal(address(s_token), OWNER, type(uint256).max); - setUpRamps(); - - s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); - s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); - - s_usdcTokenPool = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - - s_usdcTokenPoolTransferLiquidity = - new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(address(s_token)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(chainUpdates); - - USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); - domains[0] = USDCTokenPool.DomainUpdate({ - destChainSelector: DEST_CHAIN_SELECTOR, - domainIdentifier: 9999, - allowedCaller: keccak256("allowedCaller"), - enabled: true - }); - - s_usdcTokenPool.setDomains(domains); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - } - - function setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMN)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - address[] memory offRamps = new address[](1); - offRamps[0] = s_routerAllowedOffRamp; - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); - - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - function _generateUSDCMessage( - USDCMessage memory usdcMessage - ) internal pure returns (bytes memory) { - return abi.encodePacked( - usdcMessage.version, - usdcMessage.sourceDomain, - usdcMessage.destinationDomain, - usdcMessage.nonce, - usdcMessage.sender, - usdcMessage.recipient, - usdcMessage.destinationCaller, - usdcMessage.messageBody - ); - } -} - -contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { - function test_LockOrBurn_onLockReleaseMechanism_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), - "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" - ); - - uint256 amount = 1e6; - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - vm.expectEmit(); - emit TokenPool.Locked(s_routerAllowedOnRamp, amount); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); - } - - function test_MintOrRelease_OnLockReleaseMechanism_Success() public { - address recipient = address(1234); - - // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = SOURCE_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), - "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" - ); - - vm.startPrank(OWNER); - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - - // Add 1e12 liquidity so that there's enough to release - vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); - - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e12; - s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - uint256 amount = 1e6; - - vm.startPrank(s_routerAllowedOffRamp); - - vm.expectEmit(); - emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); - - Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), - offchainTokenData: "" - }) - ); - - assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); - - // Simulate the off-ramp forwarding tokens to the recipient on destination chain - // s_token.transfer(recipient, amount); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - liquidityAmount - amount, - "Incorrect remaining liquidity in TokenPool" - ); - assertEq(s_token.balanceOf(recipient), amount, "Tokens not transferred to recipient"); - } - - function test_LockOrBurn_PrimaryMechanism_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - uint256 amount = 1; - - vm.startPrank(OWNER); - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPool), - receiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - } - - // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 - function test_MintOrRelease_incomingMessageWithPrimaryMechanism() public { - bytes memory encodedUsdcMessage = - hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; - bytes memory attestation = bytes("attestation bytes"); - - uint32 nonce = 4730; - uint32 sourceDomain = 3; - uint256 amount = 100; - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - // The mocked receiver does not release the token to the pool, so we manually do it here - deal(address(s_token), address(s_usdcTokenPool), amount); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); - - vm.expectCall( - address(s_mockUSDCTransmitter), - abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) - ); - - vm.startPrank(s_routerAllowedOffRamp); - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - function test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() public { - // Test Enabling the LR mechanism and sending an outgoing message - test_LockOrBurn_PrimaryMechanism_Success(); - - // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message - uint64[] memory destChainRemoves = new uint64[](1); - destChainRemoves[0] = DEST_CHAIN_SELECTOR; - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); - - // Send an outgoing message - test_LockOrBurn_PrimaryMechanism_Success(); - } - - function test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() public { - test_MintOrRelease_OnLockReleaseMechanism_Success(); - - // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message - uint64[] memory destChainRemoves = new uint64[](1); - destChainRemoves[0] = SOURCE_CHAIN_SELECTOR; - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(SOURCE_CHAIN_SELECTOR); - - s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(OWNER, OWNER, SOURCE_CHAIN_SELECTOR); - - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - - // Test incoming on the primary mechanism after disable LR, simulating Circle's new support for CCTP on - // DEST_CHAIN_SELECTOR - test_MintOrRelease_incomingMessageWithPrimaryMechanism(); - } - - function test_LockOrBurn_WhileMigrationPause_Revert() public { - // Create a fake migration proposal - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), DEST_CHAIN_SELECTOR); - - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), - "Lock Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" - ); - - uint256 amount = 1e6; - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - // Expect the lockOrBurn to fail because a pending CCTP-Migration has paused outgoing messages on CCIP - vm.expectRevert( - abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) - ); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_ReleaseOrMint_WhileMigrationPause_Revert() public { - address recipient = address(1234); - - // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = SOURCE_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), - "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" - ); - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationProposed(SOURCE_CHAIN_SELECTOR); - - // Propose the migration to CCTP - s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory sourcePoolDataLockRelease = abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()); - - uint256 amount = 1e6; - - vm.startPrank(s_routerAllowedOffRamp); - - // Expect revert because the lane is paused and no incoming messages should be allowed - vm.expectRevert( - abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, SOURCE_CHAIN_SELECTOR) - ); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourcePoolDataLockRelease, - offchainTokenData: "" - }) - ); - } - - function test_transferLiquidity_Success() public { - // Set as the OWNER so we can provide liquidity - vm.startPrank(OWNER); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e9; - - // Provide some liquidity to the pool - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); - - // Set the new token pool as the rebalancer - s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); - - vm.expectEmit(); - emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPoolTransferLiquidity), liquidityAmount); - - vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( - address(s_usdcTokenPool), DEST_CHAIN_SELECTOR, liquidityAmount - ); - - s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); - - assertEq( - s_usdcTokenPool.owner(), - address(s_usdcTokenPoolTransferLiquidity), - "Ownership of the old pool should be transferred to the new pool" - ); - - assertEq( - s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - liquidityAmount, - "Tokens locked for dest chain doesn't match expected amount in storage" - ); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - 0, - "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" - ); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPoolTransferLiquidity)), - liquidityAmount, - "Liquidity amount of tokens should be new in new pool, but aren't" - ); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - 0, - "Liquidity amount of tokens should be zero in old pool, but aren't" - ); - } - - function test_cannotTransferLiquidityDuringPendingMigration_Revert() public { - // Set as the OWNER so we can provide liquidity - vm.startPrank(OWNER); - - s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - uint256 liquidityAmount = 1e9; - - // Provide some liquidity to the pool - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); - - // Set the new token pool as the rebalancer - s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); - - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - vm.expectRevert( - abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) - ); - - s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); - } -} - -contract HybridUSDCTokenPoolMigrationTests is HybridUSDCTokenPoolTests { - function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - assertTrue( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), - "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" - ); - - uint256 amount = 1e6; - - s_token.transfer(address(s_usdcTokenPool), amount); - - vm.startPrank(s_routerAllowedOnRamp); - - vm.expectEmit(); - emit TokenPool.Locked(s_routerAllowedOnRamp, amount); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - // Ensure that the tokens are properly locked - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - amount, - "Internal locked token accounting is incorrect" - ); - - vm.startPrank(OWNER); - - vm.expectEmit(); - emit USDCBridgeMigrator.CircleMigratorAddressSet(CIRCLE); - - s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); - - // Propose the migration to CCTP - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - assertEq( - s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), - DEST_CHAIN_SELECTOR, - "Current proposed chain migration does not match expected for DEST_CHAIN_SELECTOR" - ); - - // Impersonate the set circle address and execute the proposal - vm.startPrank(CIRCLE); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationExecuted(DEST_CHAIN_SELECTOR, amount); - - // Ensure the call to the burn function is properly - vm.expectCall(address(s_token), abi.encodeWithSelector(bytes4(keccak256("burn(uint256)")), amount)); - - s_usdcTokenPool.burnLockedUSDC(); - - // Assert that the tokens were actually burned - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens were not burned out of the tokenPool"); - - // Ensure the proposal slot was cleared and there's no tokens locked for the destination chain anymore - assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), 0, "Proposal Slot should be empty"); - assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - 0, - "No tokens should be locked for DEST_CHAIN_SELECTOR after CCTP-approved burn" - ); - - assertFalse( - s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" - ); - - test_LockOrBurn_PrimaryMechanism_Success(); - } - - function test_cancelExistingCCTPMigrationProposal() public { - vm.startPrank(OWNER); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); - - assertEq( - s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), - DEST_CHAIN_SELECTOR, - "migration proposal should exist, but doesn't" - ); - - vm.expectEmit(); - emit USDCBridgeMigrator.CCTPMigrationCancelled(DEST_CHAIN_SELECTOR); - - s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); - - assertEq( - s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), - 0, - "migration proposal exists, but shouldn't after being cancelled" - ); - - vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); - s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); - } - - function test_burnLockedUSDC_invalidPermissions_Revert() public { - address CIRCLE = makeAddr("CIRCLE"); - - vm.startPrank(OWNER); - - // Set the circle migrator address for later, but don't start pranking as it yet - s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); - - vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.onlyCircle.selector)); - - // Should fail because only Circle can call this function - s_usdcTokenPool.burnLockedUSDC(); - - vm.startPrank(CIRCLE); - - vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.ExistingMigrationProposal.selector)); - s_usdcTokenPool.burnLockedUSDC(); - } - - function test_cannotModifyLiquidityWithoutPermissions_Revert() public { - address randomAddr = makeAddr("RANDOM"); - - vm.startPrank(randomAddr); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); - - // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); - } - - function test_cannotCancelANonExistentMigrationProposal() public { - vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); - - // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert - s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); - } - - function test_unstickManualTxAfterMigration_destChain_Success() public { - address recipient = address(1234); - // Test the edge case where a tx is stuck in the manual tx queue and the destination chain is the one that - // should process is after a migration. I.E the message will have the Lock-Release flag set in the OffChainData, - // which should tell it to use the lock-release mechanism with the tokens provided. - - // We want the released amount to be 1e6, so to simulate the workflow, we sent those tokens to the contract as - // liquidity - uint256 amount = 1e6; - // Add 1e12 liquidity so that there's enough to release - vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); - - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount); - - // By Default, the source chain will be indicated as use-CCTP so we need to change that. We create a message - // that will use the Lock-Release flag in the offchain data to indicate that the tokens should be released - // instead of minted since there's no attestation for us to use. - - vm.startPrank(s_routerAllowedOffRamp); - - vm.expectEmit(); - emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), - offchainTokenData: "" - }) - ); - - // By this point, the tx should have executed, with the Lock-Release taking over, and being forwaded to the - // recipient - - assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); - assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); - - // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag - // which after a migration will mean all new messages. - - // The message should fail without an error because it failed to decode a non-existent attestation which would - // revert without an error - vm.expectRevert(); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_unstickManualTxAfterMigration_homeChain_Success() public { - address CIRCLE = makeAddr("CIRCLE"); - address recipient = address(1234); - - // Mark the destination chain as supporting CCTP, so use L/R instead. - uint64[] memory destChainAdds = new uint64[](1); - destChainAdds[0] = DEST_CHAIN_SELECTOR; - - s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); - - // Test the edge case where a tx is stuck in the manual tx queue and the source chain (mainnet) needs unsticking - // In this test we want 1e6 worth of tokens to be stuck, so first we provide liquidity to the pool >1e6 - - uint256 amount = 1e6; - // Add 1e12 liquidity so that there's enough to release - vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); - - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - // I picked 3x the amount to be stuck so that we can have enough to release with a buffer - s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount * 3); - - // At this point in the process, the router will lock new messages, so we want to simulate excluding tokens - // stuck coming back from the destination, to the home chain. This way they can be released and not minted - // since there's no corresponding attestation to use for minting. - vm.startPrank(OWNER); - - // Exclude the tokens from being burned and check for the event - vm.expectEmit(); - emit USDCBridgeMigrator.TokensExcludedFromBurn(SOURCE_CHAIN_SELECTOR, amount, (amount * 3) - amount); - - s_usdcTokenPool.excludeTokensFromBurn(SOURCE_CHAIN_SELECTOR, amount); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), - (amount * 3), - "Tokens locked minus ones excluded from the burn should be 2e6" - ); - - assertEq( - s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), - 1e6, - "1e6 tokens should be excluded from the burn" - ); - - s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); - - s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); - - vm.startPrank(CIRCLE); - - s_usdcTokenPool.burnLockedUSDC(); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), 0, "All tokens should be burned out of the pool" - ); - - assertEq( - s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), - 1e6, - "There should still be 1e6 tokens excluded from the burn" - ); - - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 1e6, "All tokens minus the excluded should be in the pool"); - - // Now that the burn is successful, we can release the tokens that were excluded from the burn - vm.startPrank(s_routerAllowedOffRamp); - - vm.expectEmit(); - emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), - offchainTokenData: "" - }) - ); - - assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); - assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); - assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); - assertEq( - s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), - 0, - "All tokens should be released from the exclusion list" - ); - - // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag - test_MintOrRelease_incomingMessageWithPrimaryMechanism(); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol deleted file mode 100644 index eea7f2af4c..0000000000 --- a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool.t.sol +++ /dev/null @@ -1,438 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IPoolV1} from "../../interfaces/IPool.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; - -contract LockReleaseTokenPoolSetup is RouterSetup { - IERC20 internal s_token; - LockReleaseTokenPool internal s_lockReleaseTokenPool; - LockReleaseTokenPool internal s_lockReleaseTokenPoolWithAllowList; - address[] internal s_allowedList; - - address internal s_allowedOnRamp = address(123); - address internal s_allowedOffRamp = address(234); - - address internal s_destPoolAddress = address(2736782345); - address internal s_sourcePoolAddress = address(53852352095); - - function setUp() public virtual override { - RouterSetup.setUp(); - s_token = new BurnMintERC677("LINK", "LNK", 18, 0); - deal(address(s_token), OWNER, type(uint256).max); - s_lockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - - s_allowedList.push(USER_1); - s_allowedList.push(DUMMY_CONTRACT_ADDRESS); - s_lockReleaseTokenPoolWithAllowList = - new LockReleaseTokenPool(s_token, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter)); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destPoolAddress), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPool.setRebalancer(OWNER); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } -} - -contract LockReleaseTokenPool_setRebalancer is LockReleaseTokenPoolSetup { - function test_SetRebalancer_Success() public { - assertEq(address(s_lockReleaseTokenPool.getRebalancer()), OWNER); - s_lockReleaseTokenPool.setRebalancer(STRANGER); - assertEq(address(s_lockReleaseTokenPool.getRebalancer()), STRANGER); - } - - function test_SetRebalancer_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_lockReleaseTokenPool.setRebalancer(STRANGER); - } -} - -contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { - function test_Fuzz_LockOrBurnNoAllowList_Success( - uint256 amount - ) public { - amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); - vm.startPrank(s_allowedOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit TokenPool.Locked(s_allowedOnRamp, amount); - - s_lockReleaseTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: STRANGER, - receiver: bytes(""), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_LockOrBurnWithAllowList_Success() public { - uint256 amount = 100; - vm.startPrank(s_allowedOnRamp); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit TokenPool.Locked(s_allowedOnRamp, amount); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[0], - receiver: bytes(""), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - vm.expectEmit(); - emit TokenPool.Locked(s_allowedOnRamp, amount); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[1], - receiver: bytes(""), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_LockOrBurnWithAllowList_Revert() public { - vm.startPrank(s_allowedOnRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: STRANGER, - receiver: bytes(""), - amount: 100, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_PoolBurnRevertNotHealthy_Revert() public { - // Should not burn tokens if cursed. - s_mockRMN.setGlobalCursed(true); - uint256 before = s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)); - - vm.startPrank(s_allowedOnRamp); - vm.expectRevert(TokenPool.CursedByRMN.selector); - - s_lockReleaseTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[0], - receiver: bytes(""), - amount: 1e5, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)), before); - } -} - -contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { - function setUp() public virtual override { - LockReleaseTokenPoolSetup.setUp(); - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_sourcePoolAddress), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); - s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(chainUpdate); - } - - function test_ReleaseOrMint_Success() public { - vm.startPrank(s_allowedOffRamp); - - uint256 amount = 100; - deal(address(s_token), address(s_lockReleaseTokenPool), amount); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit TokenPool.Released(s_allowedOffRamp, OWNER, amount); - - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_sourcePoolAddress), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_Fuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { - // Since the owner already has tokens this would break the checks - vm.assume(recipient != OWNER); - vm.assume(recipient != address(0)); - vm.assume(recipient != address(s_token)); - - // Makes sure the pool always has enough funds - deal(address(s_token), address(s_lockReleaseTokenPool), amount); - vm.startPrank(s_allowedOffRamp); - - uint256 capacity = _getInboundRateLimiterConfig().capacity; - // Determine if we hit the rate limit or the txs should succeed. - if (amount > capacity) { - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) - ); - } else { - // Only rate limit if the amount is >0 - if (amount > 0) { - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - } - - vm.expectEmit(); - emit TokenPool.Released(s_allowedOffRamp, recipient, amount); - } - - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_sourcePoolAddress), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_ChainNotAllowed_Revert() public { - address notAllowedRemotePoolAddress = address(1); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(notAllowedRemotePoolAddress), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - s_lockReleaseTokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(s_allowedOffRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, SOURCE_CHAIN_SELECTOR)); - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1e5, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: abi.encode(s_sourcePoolAddress), - sourcePoolData: "", - offchainTokenData: "" - }) - ); - } - - function test_PoolMintNotHealthy_Revert() public { - // Should not mint tokens if cursed. - s_mockRMN.setGlobalCursed(true); - uint256 before = s_token.balanceOf(OWNER); - vm.startPrank(s_allowedOffRamp); - vm.expectRevert(TokenPool.CursedByRMN.selector); - s_lockReleaseTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: bytes(""), - receiver: OWNER, - amount: 1e5, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, - sourcePoolData: _generateSourceTokenData().extraData, - offchainTokenData: "" - }) - ); - - assertEq(s_token.balanceOf(OWNER), before); - } -} - -contract LockReleaseTokenPool_canAcceptLiquidity is LockReleaseTokenPoolSetup { - function test_CanAcceptLiquidity_Success() public { - assertEq(true, s_lockReleaseTokenPool.canAcceptLiquidity()); - - s_lockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - assertEq(false, s_lockReleaseTokenPool.canAcceptLiquidity()); - } -} - -contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { - function test_Fuzz_ProvideLiquidity_Success( - uint256 amount - ) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPool), amount); - - s_lockReleaseTokenPool.provideLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre - amount); - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), amount); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPool.provideLiquidity(1); - } - - function test_Fuzz_ExceedsAllowance( - uint256 amount - ) public { - vm.assume(amount > 0); - vm.expectRevert("ERC20: insufficient allowance"); - s_lockReleaseTokenPool.provideLiquidity(amount); - } - - function test_LiquidityNotAccepted_Revert() public { - s_lockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), false, address(s_sourceRouter)); - - vm.expectRevert(LockReleaseTokenPool.LiquidityNotAccepted.selector); - s_lockReleaseTokenPool.provideLiquidity(1); - } -} - -contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { - function test_Fuzz_WithdrawalLiquidity_Success( - uint256 amount - ) public { - uint256 balancePre = s_token.balanceOf(OWNER); - s_token.approve(address(s_lockReleaseTokenPool), amount); - s_lockReleaseTokenPool.provideLiquidity(amount); - - s_lockReleaseTokenPool.withdrawLiquidity(amount); - - assertEq(s_token.balanceOf(OWNER), balancePre); - } - - // Reverts - - function test_Unauthorized_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - - s_lockReleaseTokenPool.withdrawLiquidity(1); - } - - function test_InsufficientLiquidity_Revert() public { - uint256 maxUint256 = 2 ** 256 - 1; - s_token.approve(address(s_lockReleaseTokenPool), maxUint256); - s_lockReleaseTokenPool.provideLiquidity(maxUint256); - - vm.startPrank(address(s_lockReleaseTokenPool)); - s_token.transfer(OWNER, maxUint256); - vm.startPrank(OWNER); - - vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); - s_lockReleaseTokenPool.withdrawLiquidity(1); - } -} - -contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { - LockReleaseTokenPool internal s_oldLockReleaseTokenPool; - uint256 internal s_amount = 100000; - - function setUp() public virtual override { - super.setUp(); - - s_oldLockReleaseTokenPool = - new LockReleaseTokenPool(s_token, new address[](0), address(s_mockRMN), true, address(s_sourceRouter)); - - deal(address(s_token), address(s_oldLockReleaseTokenPool), s_amount); - } - - function test_transferLiquidity_Success() public { - uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); - - s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); - - vm.expectEmit(); - emit LockReleaseTokenPool.LiquidityTransferred(address(s_oldLockReleaseTokenPool), s_amount); - - s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount); - - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre + s_amount); - } - - function test_transferLiquidity_transferTooMuch_Revert() public { - uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); - - s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); - - vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); - s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount + 1); - - assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre); - } -} - -contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { - function test_SupportsInterface_Success() public view { - assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IPoolV1).interfaceId)); - assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IERC165).interfaceId)); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol new file mode 100644 index 0000000000..63b6e0bc35 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.canAcceptLiquidity.t.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +contract LockReleaseTokenPool_canAcceptLiquidity is LockReleaseTokenPoolSetup { + function test_CanAcceptLiquidity_Success() public { + assertEq(true, s_lockReleaseTokenPool.canAcceptLiquidity()); + + s_lockReleaseTokenPool = new LockReleaseTokenPool( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), false, address(s_sourceRouter) + ); + assertEq(false, s_lockReleaseTokenPool.canAcceptLiquidity()); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol new file mode 100644 index 0000000000..7c87fbcc95 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.lockOrBurn.t.sol @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +contract LockReleaseTokenPool_lockOrBurn is LockReleaseTokenPoolSetup { + function testFuzz_LockOrBurnNoAllowList_Success( + uint256 amount + ) public { + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); + vm.startPrank(s_allowedOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, amount); + + s_lockReleaseTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_LockOrBurnWithAllowList_Success() public { + uint256 amount = 100; + vm.startPrank(s_allowedOnRamp); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, amount); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[0], + receiver: bytes(""), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + vm.expectEmit(); + emit TokenPool.Locked(s_allowedOnRamp, amount); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[1], + receiver: bytes(""), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_LockOrBurnWithAllowList_Revert() public { + vm.startPrank(s_allowedOnRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: bytes(""), + amount: 100, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_PoolBurnRevertNotHealthy_Revert() public { + // Should not burn tokens if cursed. + s_mockRMN.setGlobalCursed(true); + uint256 before = s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)); + + vm.startPrank(s_allowedOnRamp); + vm.expectRevert(TokenPool.CursedByRMN.selector); + + s_lockReleaseTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[0], + receiver: bytes(""), + amount: 1e5, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPoolWithAllowList)), before); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol new file mode 100644 index 0000000000..6ef52e8846 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.provideLiquidity.t.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +contract LockReleaseTokenPool_provideLiquidity is LockReleaseTokenPoolSetup { + function testFuzz_ProvideLiquidity_Success( + uint256 amount + ) public { + uint256 balancePre = s_token.balanceOf(OWNER); + s_token.approve(address(s_lockReleaseTokenPool), amount); + + s_lockReleaseTokenPool.provideLiquidity(amount); + + assertEq(s_token.balanceOf(OWNER), balancePre - amount); + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), amount); + } + + // Reverts + + function test_Unauthorized_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); + + s_lockReleaseTokenPool.provideLiquidity(1); + } + + function testFuzz_ExceedsAllowance( + uint256 amount + ) public { + vm.assume(amount > 0); + vm.expectRevert("ERC20: insufficient allowance"); + s_lockReleaseTokenPool.provideLiquidity(amount); + } + + function test_LiquidityNotAccepted_Revert() public { + s_lockReleaseTokenPool = new LockReleaseTokenPool( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), false, address(s_sourceRouter) + ); + + vm.expectRevert(LockReleaseTokenPool.LiquidityNotAccepted.selector); + s_lockReleaseTokenPool.provideLiquidity(1); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol new file mode 100644 index 0000000000..9a67f76644 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.releaseOrMint.t.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +contract LockReleaseTokenPool_releaseOrMint is LockReleaseTokenPoolSetup { + function setUp() public virtual override { + LockReleaseTokenPoolSetup.setUp(); + + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_sourcePoolAddress); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_lockReleaseTokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(new uint64[](0), chainUpdate); + } + + function test_ReleaseOrMint_Success() public { + vm.startPrank(s_allowedOffRamp); + + uint256 amount = 100; + deal(address(s_token), address(s_lockReleaseTokenPool), amount); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit TokenPool.Released(s_allowedOffRamp, OWNER, amount); + + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_sourcePoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function testFuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { + // Since the owner already has tokens this would break the checks + vm.assume(recipient != OWNER); + vm.assume(recipient != address(0)); + vm.assume(recipient != address(s_token)); + + // Makes sure the pool always has enough funds + deal(address(s_token), address(s_lockReleaseTokenPool), amount); + vm.startPrank(s_allowedOffRamp); + + uint256 capacity = _getInboundRateLimiterConfig().capacity; + // Determine if we hit the rate limit or the txs should succeed. + if (amount > capacity) { + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) + ); + } else { + // Only rate limit if the amount is >0 + if (amount > 0) { + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + } + + vm.expectEmit(); + emit TokenPool.Released(s_allowedOffRamp, recipient, amount); + } + + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_sourcePoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_ChainNotAllowed_Revert() public { + uint64[] memory chainsToRemove = new uint64[](1); + chainsToRemove[0] = SOURCE_CHAIN_SELECTOR; + + s_lockReleaseTokenPool.applyChainUpdates(chainsToRemove, new TokenPool.ChainUpdate[](0)); + + vm.startPrank(s_allowedOffRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, SOURCE_CHAIN_SELECTOR)); + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1e5, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: abi.encode(s_sourcePoolAddress), + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_PoolMintNotHealthy_Revert() public { + // Should not mint tokens if cursed. + s_mockRMN.setGlobalCursed(true); + uint256 before = s_token.balanceOf(OWNER); + vm.startPrank(s_allowedOffRamp); + vm.expectRevert(TokenPool.CursedByRMN.selector); + s_lockReleaseTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: bytes(""), + receiver: OWNER, + amount: 1e5, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: _generateSourceTokenData().sourcePoolAddress, + sourcePoolData: _generateSourceTokenData().extraData, + offchainTokenData: "" + }) + ); + + assertEq(s_token.balanceOf(OWNER), before); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol new file mode 100644 index 0000000000..25286c1a37 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.setRebalancer.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +contract LockReleaseTokenPool_setRebalancer is LockReleaseTokenPoolSetup { + function test_SetRebalancer_Success() public { + assertEq(address(s_lockReleaseTokenPool.getRebalancer()), OWNER); + s_lockReleaseTokenPool.setRebalancer(STRANGER); + assertEq(address(s_lockReleaseTokenPool.getRebalancer()), STRANGER); + } + + function test_SetRebalancer_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); + s_lockReleaseTokenPool.setRebalancer(STRANGER); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol new file mode 100644 index 0000000000..9a08fc38c9 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.supportsInterface.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IPoolV1} from "../../../interfaces/IPool.sol"; + +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +import {IERC165} from "../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + +contract LockReleaseTokenPool_supportsInterface is LockReleaseTokenPoolSetup { + function test_SupportsInterface_Success() public view { + assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IPoolV1).interfaceId)); + assertTrue(s_lockReleaseTokenPool.supportsInterface(type(IERC165).interfaceId)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol new file mode 100644 index 0000000000..60b9c935bd --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.transferLiquidity.t.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +contract LockReleaseTokenPool_transferLiquidity is LockReleaseTokenPoolSetup { + LockReleaseTokenPool internal s_oldLockReleaseTokenPool; + uint256 internal s_amount = 100000; + + function setUp() public virtual override { + super.setUp(); + + s_oldLockReleaseTokenPool = new LockReleaseTokenPool( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, address(s_sourceRouter) + ); + + deal(address(s_token), address(s_oldLockReleaseTokenPool), s_amount); + } + + function test_transferLiquidity_Success() public { + uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); + + s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); + + vm.expectEmit(); + emit LockReleaseTokenPool.LiquidityTransferred(address(s_oldLockReleaseTokenPool), s_amount); + + s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount); + + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre + s_amount); + } + + function test_transferLiquidity_transferTooMuch_Revert() public { + uint256 balancePre = s_token.balanceOf(address(s_lockReleaseTokenPool)); + + s_oldLockReleaseTokenPool.setRebalancer(address(s_lockReleaseTokenPool)); + + vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); + s_lockReleaseTokenPool.transferLiquidity(address(s_oldLockReleaseTokenPool), s_amount + 1); + + assertEq(s_token.balanceOf(address(s_lockReleaseTokenPool)), balancePre); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol new file mode 100644 index 0000000000..29b6ef6c7f --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.withdrawalLiquidity.t.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {LockReleaseTokenPoolSetup} from "./LockReleaseTokenPoolSetup.t.sol"; + +contract LockReleaseTokenPool_withdrawalLiquidity is LockReleaseTokenPoolSetup { + function testFuzz_WithdrawalLiquidity_Success( + uint256 amount + ) public { + uint256 balancePre = s_token.balanceOf(OWNER); + s_token.approve(address(s_lockReleaseTokenPool), amount); + s_lockReleaseTokenPool.provideLiquidity(amount); + + s_lockReleaseTokenPool.withdrawLiquidity(amount); + + assertEq(s_token.balanceOf(OWNER), balancePre); + } + + // Reverts + function test_Unauthorized_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); + + s_lockReleaseTokenPool.withdrawLiquidity(1); + } + + function test_InsufficientLiquidity_Revert() public { + uint256 maxUint256 = 2 ** 256 - 1; + s_token.approve(address(s_lockReleaseTokenPool), maxUint256); + s_lockReleaseTokenPool.provideLiquidity(maxUint256); + + vm.startPrank(address(s_lockReleaseTokenPool)); + s_token.transfer(OWNER, maxUint256); + vm.startPrank(OWNER); + + vm.expectRevert(LockReleaseTokenPool.InsufficientLiquidity.selector); + s_lockReleaseTokenPool.withdrawLiquidity(1); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol new file mode 100644 index 0000000000..44f380720f --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; +import {Router} from "../../../Router.sol"; +import {LockReleaseTokenPool} from "../../../pools/LockReleaseTokenPool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {RouterSetup} from "../../router/RouterSetup.t.sol"; + +contract LockReleaseTokenPoolSetup is RouterSetup { + IERC20 internal s_token; + LockReleaseTokenPool internal s_lockReleaseTokenPool; + LockReleaseTokenPool internal s_lockReleaseTokenPoolWithAllowList; + address[] internal s_allowedList; + + address internal s_allowedOnRamp = address(123); + address internal s_allowedOffRamp = address(234); + + address internal s_destPoolAddress = address(2736782345); + address internal s_sourcePoolAddress = address(53852352095); + + function setUp() public virtual override { + RouterSetup.setUp(); + s_token = new BurnMintERC20("LINK", "LNK", 18, 0, 0); + deal(address(s_token), OWNER, type(uint256).max); + s_lockReleaseTokenPool = new LockReleaseTokenPool( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), true, address(s_sourceRouter) + ); + + s_allowedList.push(USER_1); + s_allowedList.push(OWNER); + s_lockReleaseTokenPoolWithAllowList = new LockReleaseTokenPool( + s_token, DEFAULT_TOKEN_DECIMALS, s_allowedList, address(s_mockRMN), true, address(s_sourceRouter) + ); + + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_destPoolAddress); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_lockReleaseTokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + s_lockReleaseTokenPoolWithAllowList.applyChainUpdates(new uint64[](0), chainUpdate); + s_lockReleaseTokenPool.setRebalancer(OWNER); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_allowedOnRamp}); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: s_allowedOffRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol deleted file mode 100644 index 766a4870f6..0000000000 --- a/contracts/src/v0.8/ccip/test/pools/TokenPool.t.sol +++ /dev/null @@ -1,785 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {TokenPoolHelper} from "../helpers/TokenPoolHelper.sol"; -import {RouterSetup} from "../router/RouterSetup.t.sol"; - -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; - -contract TokenPoolSetup is RouterSetup { - IERC20 internal s_token; - TokenPoolHelper internal s_tokenPool; - - function setUp() public virtual override { - RouterSetup.setUp(); - s_token = new BurnMintERC677("LINK", "LNK", 18, 0); - deal(address(s_token), OWNER, type(uint256).max); - - s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - } -} - -contract TokenPool_constructor is TokenPoolSetup { - function test_immutableFields_Success() public view { - assertEq(address(s_token), address(s_tokenPool.getToken())); - assertEq(address(s_mockRMN), s_tokenPool.getRmnProxy()); - assertEq(false, s_tokenPool.getAllowListEnabled()); - assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); - } - - // Reverts - function test_ZeroAddressNotAllowed_Revert() public { - vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - - s_tokenPool = new TokenPoolHelper(IERC20(address(0)), new address[](0), address(s_mockRMN), address(s_sourceRouter)); - } -} - -contract TokenPool_getRemotePool is TokenPoolSetup { - function test_getRemotePool_Success() public { - uint64 chainSelector = 123124; - address remotePool = makeAddr("remotePool"); - address remoteToken = makeAddr("remoteToken"); - - // Zero indicates nothing is set - assertEq(0, s_tokenPool.getRemotePool(chainSelector).length); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(remotePool), - remoteTokenAddress: abi.encode(remoteToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdates); - - assertEq(remotePool, abi.decode(s_tokenPool.getRemotePool(chainSelector), (address))); - } -} - -contract TokenPool_setRemotePool is TokenPoolSetup { - function test_setRemotePool_Success() public { - uint64 chainSelector = DEST_CHAIN_SELECTOR; - address initialPool = makeAddr("remotePool"); - address remoteToken = makeAddr("remoteToken"); - // The new pool is a non-evm pool, as it doesn't fit in the normal 160 bits - bytes memory newPool = abi.encode(type(uint256).max); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(initialPool), - remoteTokenAddress: abi.encode(remoteToken), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdates); - - vm.expectEmit(); - emit TokenPool.RemotePoolSet(chainSelector, abi.encode(initialPool), newPool); - - s_tokenPool.setRemotePool(chainSelector, newPool); - - assertEq(keccak256(newPool), keccak256(s_tokenPool.getRemotePool(chainSelector))); - } - - // Reverts - - function test_setRemotePool_NonExistentChain_Reverts() public { - uint64 chainSelector = 123124; - bytes memory remotePool = abi.encode(makeAddr("remotePool")); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); - s_tokenPool.setRemotePool(chainSelector, remotePool); - } - - function test_setRemotePool_OnlyOwner_Reverts() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_tokenPool.setRemotePool(123124, abi.encode(makeAddr("remotePool"))); - } -} - -contract TokenPool_applyChainUpdates is TokenPoolSetup { - function assertState( - TokenPool.ChainUpdate[] memory chainUpdates - ) public view { - uint64[] memory chainSelectors = s_tokenPool.getSupportedChains(); - for (uint256 i = 0; i < chainUpdates.length; i++) { - assertEq(chainUpdates[i].remoteChainSelector, chainSelectors[i]); - } - - for (uint256 i = 0; i < chainUpdates.length; ++i) { - assertTrue(s_tokenPool.isSupportedChain(chainUpdates[i].remoteChainSelector)); - RateLimiter.TokenBucket memory bkt = - s_tokenPool.getCurrentOutboundRateLimiterState(chainUpdates[i].remoteChainSelector); - assertEq(bkt.capacity, chainUpdates[i].outboundRateLimiterConfig.capacity); - assertEq(bkt.rate, chainUpdates[i].outboundRateLimiterConfig.rate); - assertEq(bkt.isEnabled, chainUpdates[i].outboundRateLimiterConfig.isEnabled); - - bkt = s_tokenPool.getCurrentInboundRateLimiterState(chainUpdates[i].remoteChainSelector); - assertEq(bkt.capacity, chainUpdates[i].inboundRateLimiterConfig.capacity); - assertEq(bkt.rate, chainUpdates[i].inboundRateLimiterConfig.rate); - assertEq(bkt.isEnabled, chainUpdates[i].inboundRateLimiterConfig.isEnabled); - } - } - - function test_applyChainUpdates_Success() public { - RateLimiter.Config memory outboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); - RateLimiter.Config memory inboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e29, rate: 1e19}); - RateLimiter.Config memory outboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e26, rate: 1e16}); - RateLimiter.Config memory inboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e27, rate: 1e17}); - - // EVM chain, which uses the 160 bit evm address space - uint64 evmChainSelector = 1; - bytes memory evmRemotePool = abi.encode(makeAddr("evm_remote_pool")); - bytes memory evmRemoteToken = abi.encode(makeAddr("evm_remote_token")); - - // Non EVM chain, which uses the full 256 bits - uint64 nonEvmChainSelector = type(uint64).max; - bytes memory nonEvmRemotePool = abi.encode(keccak256("non_evm_remote_pool")); - bytes memory nonEvmRemoteToken = abi.encode(keccak256("non_evm_remote_token")); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: evmChainSelector, - remotePoolAddress: evmRemotePool, - remoteTokenAddress: evmRemoteToken, - allowed: true, - outboundRateLimiterConfig: outboundRateLimit1, - inboundRateLimiterConfig: inboundRateLimit1 - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: nonEvmChainSelector, - remotePoolAddress: nonEvmRemotePool, - remoteTokenAddress: nonEvmRemoteToken, - allowed: true, - outboundRateLimiterConfig: outboundRateLimit2, - inboundRateLimiterConfig: inboundRateLimit2 - }); - - // Assert configuration is applied - vm.expectEmit(); - emit TokenPool.ChainAdded( - chainUpdates[0].remoteChainSelector, - chainUpdates[0].remoteTokenAddress, - chainUpdates[0].outboundRateLimiterConfig, - chainUpdates[0].inboundRateLimiterConfig - ); - vm.expectEmit(); - emit TokenPool.ChainAdded( - chainUpdates[1].remoteChainSelector, - chainUpdates[1].remoteTokenAddress, - chainUpdates[1].outboundRateLimiterConfig, - chainUpdates[1].inboundRateLimiterConfig - ); - s_tokenPool.applyChainUpdates(chainUpdates); - // on1: rateLimit1, on2: rateLimit2, off1: rateLimit1, off2: rateLimit3 - assertState(chainUpdates); - - // Removing an non-existent chain should revert - TokenPool.ChainUpdate[] memory chainRemoves = new TokenPool.ChainUpdate[](1); - uint64 strangerChainSelector = 120938; - chainRemoves[0] = TokenPool.ChainUpdate({ - remoteChainSelector: strangerChainSelector, - remotePoolAddress: evmRemotePool, - remoteTokenAddress: evmRemoteToken, - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, strangerChainSelector)); - s_tokenPool.applyChainUpdates(chainRemoves); - // State remains - assertState(chainUpdates); - - // Can remove a chain - chainRemoves[0].remoteChainSelector = evmChainSelector; - - vm.expectEmit(); - emit TokenPool.ChainRemoved(chainRemoves[0].remoteChainSelector); - - s_tokenPool.applyChainUpdates(chainRemoves); - - // State updated, only chain 2 remains - TokenPool.ChainUpdate[] memory singleChainConfigured = new TokenPool.ChainUpdate[](1); - singleChainConfigured[0] = chainUpdates[1]; - assertState(singleChainConfigured); - - // Cannot reset already configured ramp - vm.expectRevert( - abi.encodeWithSelector(TokenPool.ChainAlreadyExists.selector, singleChainConfigured[0].remoteChainSelector) - ); - s_tokenPool.applyChainUpdates(singleChainConfigured); - } - - // Reverts - - function test_applyChainUpdates_OnlyCallableByOwner_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - s_tokenPool.applyChainUpdates(new TokenPool.ChainUpdate[](0)); - } - - function test_applyChainUpdates_ZeroAddressNotAllowed_Revert() public { - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: "", - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) - }); - - vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(2)), - remoteTokenAddress: "", - allowed: true, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) - }); - - vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() public { - RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); - RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: outboundRateLimit, - inboundRateLimiterConfig: inboundRateLimit - }); - - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].allowed = false; - chainUpdates[0].outboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); - chainUpdates[0].inboundRateLimiterConfig = RateLimiter.Config({isEnabled: false, capacity: 10, rate: 1}); - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.DisabledNonZeroRateLimit.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_applyChainUpdates_NonExistentChain_Revert() public { - RateLimiter.Config memory outboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); - RateLimiter.Config memory inboundRateLimit = RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: outboundRateLimit, - inboundRateLimiterConfig: inboundRateLimit - }); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainUpdates[0].remoteChainSelector)); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_applyChainUpdates_InvalidRateLimitRate_Revert() public { - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: 1, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}) - }); - - // Outbound - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].outboundRateLimiterConfig.rate = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].outboundRateLimiterConfig.capacity = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].outboundRateLimiterConfig.capacity = 101; - - s_tokenPool.applyChainUpdates(chainUpdates); - - // Change the chain selector as adding the same one would revert - chainUpdates[0].remoteChainSelector = 2; - - // Inbound - - chainUpdates[0].inboundRateLimiterConfig.capacity = 0; - chainUpdates[0].inboundRateLimiterConfig.rate = 0; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].inboundRateLimiterConfig.rate = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].inboundRateLimiterConfig.capacity = 100; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) - ); - s_tokenPool.applyChainUpdates(chainUpdates); - - chainUpdates[0].inboundRateLimiterConfig.capacity = 101; - - s_tokenPool.applyChainUpdates(chainUpdates); - } -} - -contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { - uint64 internal s_remoteChainSelector; - - function setUp() public virtual override { - TokenPoolSetup.setUp(); - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - s_remoteChainSelector = 123124; - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: s_remoteChainSelector, - remotePoolAddress: abi.encode(address(2)), - remoteTokenAddress: abi.encode(address(3)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdates); - } - - function test_Fuzz_SetChainRateLimiterConfig_Success(uint128 capacity, uint128 rate, uint32 newTime) public { - // Cap the lower bound to 4 so 4/2 is still >= 2 - vm.assume(capacity >= 4); - // Cap the lower bound to 2 so 2/2 is still >= 1 - rate = uint128(bound(rate, 2, capacity - 2)); - // Bucket updates only work on increasing time - newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); - vm.warp(newTime); - - uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector).tokens; - uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector).tokens; - - RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); - RateLimiter.Config memory newInboundConfig = - RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); - - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newOutboundConfig); - vm.expectEmit(); - emit RateLimiter.ConfigChanged(newInboundConfig); - vm.expectEmit(); - emit TokenPool.ChainConfigured(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - s_tokenPool.setChainRateLimiterConfig(s_remoteChainSelector, newOutboundConfig, newInboundConfig); - - uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); - - RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newOutboundConfig.capacity); - assertEq(bucket.rate, newOutboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - - expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); - - bucket = s_tokenPool.getCurrentInboundRateLimiterState(s_remoteChainSelector); - assertEq(bucket.capacity, newInboundConfig.capacity); - assertEq(bucket.rate, newInboundConfig.rate); - assertEq(bucket.tokens, expectedTokens); - assertEq(bucket.lastUpdated, newTime); - } - - // Reverts - - function test_OnlyOwnerOrRateLimitAdmin_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); - s_tokenPool.setChainRateLimiterConfig( - s_remoteChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() - ); - } - - function test_NonExistentChain_Revert() public { - uint64 wrongChainSelector = 9084102894; - - vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); - s_tokenPool.setChainRateLimiterConfig( - wrongChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() - ); - } -} - -contract LockRelease_setRateLimitAdmin is TokenPoolSetup { - function test_SetRateLimitAdmin_Success() public { - assertEq(address(0), s_tokenPool.getRateLimitAdmin()); - s_tokenPool.setRateLimitAdmin(OWNER); - assertEq(OWNER, s_tokenPool.getRateLimitAdmin()); - } - - // Reverts - - function test_SetRateLimitAdmin_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - s_tokenPool.setRateLimitAdmin(STRANGER); - } -} - -contract TokenPool_onlyOnRamp is TokenPoolSetup { - function test_onlyOnRamp_Success() public { - uint64 chainSelector = 13377; - address onRamp = makeAddr("onRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - vm.startPrank(onRamp); - - s_tokenPool.onlyOnRampModifier(chainSelector); - } - - function test_ChainNotAllowed_Revert() public { - uint64 chainSelector = 13377; - address onRamp = makeAddr("onRamp"); - - vm.startPrank(onRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOnRampModifier(chainSelector); - - vm.startPrank(OWNER); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); - s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - vm.startPrank(onRamp); - // Should succeed now that we've added the chain - s_tokenPool.onlyOnRampModifier(chainSelector); - - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - vm.startPrank(OWNER); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(onRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOffRampModifier(chainSelector); - } - - function test_CallerIsNotARampOnRouter_Revert() public { - uint64 chainSelector = 13377; - address onRamp = makeAddr("onRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(onRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, onRamp)); - - s_tokenPool.onlyOnRampModifier(chainSelector); - } -} - -contract TokenPool_onlyOffRamp is TokenPoolSetup { - function test_onlyOffRamp_Success() public { - uint64 chainSelector = 13377; - address offRamp = makeAddr("onRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); - - vm.startPrank(offRamp); - - s_tokenPool.onlyOffRampModifier(chainSelector); - } - - function test_ChainNotAllowed_Revert() public { - uint64 chainSelector = 13377; - address offRamp = makeAddr("onRamp"); - - vm.startPrank(offRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOffRampModifier(chainSelector); - - vm.startPrank(OWNER); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); - s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); - - vm.startPrank(offRamp); - // Should succeed now that we've added the chain - s_tokenPool.onlyOffRampModifier(chainSelector); - - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: false, - outboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}), - inboundRateLimiterConfig: RateLimiter.Config({isEnabled: false, capacity: 0, rate: 0}) - }); - - vm.startPrank(OWNER); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(offRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); - s_tokenPool.onlyOffRampModifier(chainSelector); - } - - function test_CallerIsNotARampOnRouter_Revert() public { - uint64 chainSelector = 13377; - address offRamp = makeAddr("offRamp"); - - TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); - chainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: chainSelector, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - s_tokenPool.applyChainUpdates(chainUpdate); - - vm.startPrank(offRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, offRamp)); - - s_tokenPool.onlyOffRampModifier(chainSelector); - } -} - -contract TokenPoolWithAllowListSetup is TokenPoolSetup { - address[] internal s_allowedSenders; - - function setUp() public virtual override { - TokenPoolSetup.setUp(); - - s_allowedSenders.push(STRANGER); - s_allowedSenders.push(DUMMY_CONTRACT_ADDRESS); - - s_tokenPool = new TokenPoolHelper(s_token, s_allowedSenders, address(s_mockRMN), address(s_sourceRouter)); - } -} - -contract TokenPoolWithAllowList_getAllowListEnabled is TokenPoolWithAllowListSetup { - function test_GetAllowListEnabled_Success() public view { - assertTrue(s_tokenPool.getAllowListEnabled()); - } -} - -contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { - function test_SetRouter_Success() public { - assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); - - address newRouter = makeAddr("newRouter"); - - vm.expectEmit(); - emit TokenPool.RouterUpdated(address(s_sourceRouter), newRouter); - - s_tokenPool.setRouter(newRouter); - - assertEq(newRouter, s_tokenPool.getRouter()); - } -} - -contract TokenPoolWithAllowList_getAllowList is TokenPoolWithAllowListSetup { - function test_GetAllowList_Success() public view { - address[] memory setAddresses = s_tokenPool.getAllowList(); - assertEq(2, setAddresses.length); - assertEq(s_allowedSenders[0], setAddresses[0]); - assertEq(s_allowedSenders[1], setAddresses[1]); - } -} - -contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListSetup { - function test_SetAllowList_Success() public { - address[] memory newAddresses = new address[](2); - newAddresses[0] = address(1); - newAddresses[1] = address(2); - - for (uint256 i = 0; i < 2; ++i) { - vm.expectEmit(); - emit TokenPool.AllowListAdd(newAddresses[i]); - } - - s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); - address[] memory setAddresses = s_tokenPool.getAllowList(); - - assertEq(s_allowedSenders[0], setAddresses[0]); - assertEq(s_allowedSenders[1], setAddresses[1]); - assertEq(address(1), setAddresses[2]); - assertEq(address(2), setAddresses[3]); - - // address(2) exists noop, add address(3), remove address(1) - newAddresses = new address[](2); - newAddresses[0] = address(2); - newAddresses[1] = address(3); - - address[] memory removeAddresses = new address[](1); - removeAddresses[0] = address(1); - - vm.expectEmit(); - emit TokenPool.AllowListRemove(address(1)); - - vm.expectEmit(); - emit TokenPool.AllowListAdd(address(3)); - - s_tokenPool.applyAllowListUpdates(removeAddresses, newAddresses); - setAddresses = s_tokenPool.getAllowList(); - - assertEq(s_allowedSenders[0], setAddresses[0]); - assertEq(s_allowedSenders[1], setAddresses[1]); - assertEq(address(2), setAddresses[2]); - assertEq(address(3), setAddresses[3]); - - // remove all from allowList - for (uint256 i = 0; i < setAddresses.length; ++i) { - vm.expectEmit(); - emit TokenPool.AllowListRemove(setAddresses[i]); - } - - s_tokenPool.applyAllowListUpdates(setAddresses, new address[](0)); - setAddresses = s_tokenPool.getAllowList(); - - assertEq(0, setAddresses.length); - } - - function test_SetAllowListSkipsZero_Success() public { - uint256 setAddressesLength = s_tokenPool.getAllowList().length; - - address[] memory newAddresses = new address[](1); - newAddresses[0] = address(0); - - s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); - address[] memory setAddresses = s_tokenPool.getAllowList(); - - assertEq(setAddresses.length, setAddressesLength); - } - - // Reverts - - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - address[] memory newAddresses = new address[](2); - s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); - } - - function test_AllowListNotEnabled_Revert() public { - s_tokenPool = new TokenPoolHelper(s_token, new address[](0), address(s_mockRMN), address(s_sourceRouter)); - - vm.expectRevert(TokenPool.AllowListNotEnabled.selector); - - s_tokenPool.applyAllowListUpdates(new address[](0), new address[](2)); - } -} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol new file mode 100644 index 0000000000..287ee796f6 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.addRemotePool.t.sol @@ -0,0 +1,165 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Router} from "../../../Router.sol"; +import {Pool} from "../../../libraries/Pool.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_addRemotePool is TokenPoolSetup { + function test_addRemotePool_Success() public { + // Use a longer data type to ensure it also works for non-evm + bytes memory remotePool = abi.encode(makeAddr("non-evm-1"), makeAddr("non-evm-2")); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit TokenPool.RemotePoolAdded(DEST_CHAIN_SELECTOR, remotePool); + + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePool); + + bytes[] memory remotePools = s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR); + + assertEq(remotePools.length, 2); + assertEq(remotePools[0], abi.encode(s_initialRemotePool)); + assertEq(remotePools[1], remotePool); + } + + function test_addRemotePool_MultipleActive() public { + bytes[] memory remotePools = new bytes[](3); + remotePools[0] = abi.encode(makeAddr("remotePool1")); + remotePools[1] = abi.encode(makeAddr("remotePool2")); + remotePools[2] = abi.encode(makeAddr("remotePool3")); + + address fakeOffRamp = makeAddr("fakeOffRamp"); + + vm.mockCall( + address(s_sourceRouter), abi.encodeCall(Router.isOffRamp, (DEST_CHAIN_SELECTOR, fakeOffRamp)), abi.encode(true) + ); + + vm.startPrank(fakeOffRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + + // There's already one pool setup through the test setup + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 1); + + vm.startPrank(OWNER); + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); + + vm.startPrank(fakeOffRamp); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + + // Adding an additional pool does not remove the previous one + vm.startPrank(OWNER); + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[1]); + + // Both should now work + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 3); + vm.startPrank(fakeOffRamp); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + + // Adding a third pool, and removing the first one + vm.startPrank(OWNER); + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePools[2]); + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 4); + s_tokenPool.removeRemotePool(DEST_CHAIN_SELECTOR, remotePools[0]); + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 3); + + // Only the last two should work + vm.startPrank(fakeOffRamp); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); + + // Removing the chain removes all associated pool hashes + vm.startPrank(OWNER); + + uint64[] memory chainSelectorsToRemove = new uint64[](1); + chainSelectorsToRemove[0] = DEST_CHAIN_SELECTOR; + s_tokenPool.applyChainUpdates(chainSelectorsToRemove, new TokenPool.ChainUpdate[](0)); + + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 0); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, DEST_CHAIN_SELECTOR)); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); + + // Adding the chain back should NOT allow the previous pools to work again + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: abi.encode(s_initialRemoteToken), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + vm.startPrank(OWNER); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + + vm.startPrank(fakeOffRamp); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[0])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[0])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[1])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[1])); + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidSourcePoolAddress.selector, remotePools[2])); + s_tokenPool.releaseOrMint(_getReleaseOrMintInV1(remotePools[2])); + } + + function _getReleaseOrMintInV1( + bytes memory sourcePoolAddress + ) internal view returns (Pool.ReleaseOrMintInV1 memory) { + return Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + remoteChainSelector: DEST_CHAIN_SELECTOR, + receiver: OWNER, + amount: 1000, + localToken: address(s_token), + sourcePoolAddress: sourcePoolAddress, + sourcePoolData: "", + offchainTokenData: "" + }); + } + + // Reverts + + function test_NonExistentChain_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; + bytes memory remotePool = abi.encode(type(uint256).max); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); + + s_tokenPool.addRemotePool(chainSelector, remotePool); + } + + function test_ZeroLengthAddressNotAllowed_Revert() public { + bytes memory remotePool = ""; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ZeroAddressNotAllowed.selector)); + + s_tokenPool.addRemotePool(DEST_CHAIN_SELECTOR, remotePool); + } + + function test_PoolAlreadyAdded_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + + bytes memory remotePool = abi.encode(type(uint256).max); + + vm.expectEmit(); + emit TokenPool.RemotePoolAdded(chainSelector, remotePool); + + s_tokenPool.addRemotePool(chainSelector, remotePool); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.PoolAlreadyAdded.selector, chainSelector, remotePool)); + + // Attempt to add the same pool again but revert + s_tokenPool.addRemotePool(chainSelector, remotePool); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol new file mode 100644 index 0000000000..9662944581 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyAllowListUpdates.t.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; + +import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; + +contract TokenPoolWithAllowList_applyAllowListUpdates is TokenPoolWithAllowListSetup { + function test_SetAllowList_Success() public { + address[] memory newAddresses = new address[](2); + newAddresses[0] = address(1); + newAddresses[1] = address(2); + + for (uint256 i = 0; i < 2; ++i) { + vm.expectEmit(); + emit TokenPool.AllowListAdd(newAddresses[i]); + } + + s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); + address[] memory setAddresses = s_tokenPool.getAllowList(); + + assertEq(s_allowedSenders[0], setAddresses[0]); + assertEq(s_allowedSenders[1], setAddresses[1]); + assertEq(address(1), setAddresses[2]); + assertEq(address(2), setAddresses[3]); + + // address(2) exists noop, add address(3), remove address(1) + newAddresses = new address[](2); + newAddresses[0] = address(2); + newAddresses[1] = address(3); + + address[] memory removeAddresses = new address[](1); + removeAddresses[0] = address(1); + + vm.expectEmit(); + emit TokenPool.AllowListRemove(address(1)); + + vm.expectEmit(); + emit TokenPool.AllowListAdd(address(3)); + + s_tokenPool.applyAllowListUpdates(removeAddresses, newAddresses); + setAddresses = s_tokenPool.getAllowList(); + + assertEq(s_allowedSenders[0], setAddresses[0]); + assertEq(s_allowedSenders[1], setAddresses[1]); + assertEq(address(2), setAddresses[2]); + assertEq(address(3), setAddresses[3]); + + // remove all from allowlist + for (uint256 i = 0; i < setAddresses.length; ++i) { + vm.expectEmit(); + emit TokenPool.AllowListRemove(setAddresses[i]); + } + + s_tokenPool.applyAllowListUpdates(setAddresses, new address[](0)); + setAddresses = s_tokenPool.getAllowList(); + + assertEq(0, setAddresses.length); + } + + function test_SetAllowListSkipsZero_Success() public { + uint256 setAddressesLength = s_tokenPool.getAllowList().length; + + address[] memory newAddresses = new address[](1); + newAddresses[0] = address(0); + + s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); + address[] memory setAddresses = s_tokenPool.getAllowList(); + + assertEq(setAddresses.length, setAddressesLength); + } + + // Reverts + + function test_OnlyOwner_Revert() public { + vm.stopPrank(); + vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); + address[] memory newAddresses = new address[](2); + s_tokenPool.applyAllowListUpdates(new address[](0), newAddresses); + } + + function test_AllowListNotEnabled_Revert() public { + s_tokenPool = new TokenPoolHelper( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + + vm.expectRevert(TokenPool.AllowListNotEnabled.selector); + + s_tokenPool.applyAllowListUpdates(new address[](0), new address[](2)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol new file mode 100644 index 0000000000..52fd5cd624 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; +import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; + +import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; +import {RouterSetup} from "../../router/RouterSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract TokenPool_applyChainUpdates is RouterSetup { + IERC20 internal s_token; + TokenPoolHelper internal s_tokenPool; + + function setUp() public virtual override { + RouterSetup.setUp(); + s_token = new BurnMintERC677("LINK", "LNK", 18, 0); + deal(address(s_token), OWNER, type(uint256).max); + + s_tokenPool = new TokenPoolHelper( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + } + + function assertState( + TokenPool.ChainUpdate[] memory chainUpdates + ) public view { + uint64[] memory chainSelectors = s_tokenPool.getSupportedChains(); + for (uint256 i = 0; i < chainUpdates.length; ++i) { + assertEq(chainUpdates[i].remoteChainSelector, chainSelectors[i], "Chain selector mismatch"); + } + + for (uint256 i = 0; i < chainUpdates.length; ++i) { + assertTrue(s_tokenPool.isSupportedChain(chainUpdates[i].remoteChainSelector)); + RateLimiter.TokenBucket memory bkt = + s_tokenPool.getCurrentOutboundRateLimiterState(chainUpdates[i].remoteChainSelector); + assertEq(bkt.capacity, chainUpdates[i].outboundRateLimiterConfig.capacity); + assertEq(bkt.rate, chainUpdates[i].outboundRateLimiterConfig.rate); + assertEq(bkt.isEnabled, chainUpdates[i].outboundRateLimiterConfig.isEnabled); + + bkt = s_tokenPool.getCurrentInboundRateLimiterState(chainUpdates[i].remoteChainSelector); + assertEq(bkt.capacity, chainUpdates[i].inboundRateLimiterConfig.capacity); + assertEq(bkt.rate, chainUpdates[i].inboundRateLimiterConfig.rate); + assertEq(bkt.isEnabled, chainUpdates[i].inboundRateLimiterConfig.isEnabled); + } + } + + function test_applyChainUpdates_Success() public { + RateLimiter.Config memory outboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}); + RateLimiter.Config memory inboundRateLimit1 = RateLimiter.Config({isEnabled: true, capacity: 100e29, rate: 1e19}); + RateLimiter.Config memory outboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e26, rate: 1e16}); + RateLimiter.Config memory inboundRateLimit2 = RateLimiter.Config({isEnabled: true, capacity: 100e27, rate: 1e17}); + + // EVM chain, which uses the 160 bit evm address space + uint64 evmChainSelector = 1789142; + bytes memory evmRemotePool = abi.encode(makeAddr("evm_remote_pool")); + bytes memory evmRemoteToken = abi.encode(makeAddr("evm_remote_token")); + + // Non EVM chain, which uses the full 256 bits + uint64 nonEvmChainSelector = type(uint64).max; + bytes memory nonEvmRemotePool = abi.encode(keccak256("non_evm_remote_pool")); + bytes memory nonEvmRemoteToken = abi.encode(keccak256("non_evm_remote_token")); + + bytes[] memory evmRemotePools = new bytes[](1); + evmRemotePools[0] = evmRemotePool; + + bytes[] memory nonEvmRemotePools = new bytes[](1); + nonEvmRemotePools[0] = nonEvmRemotePool; + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: evmChainSelector, + remotePoolAddresses: evmRemotePools, + remoteTokenAddress: evmRemoteToken, + outboundRateLimiterConfig: outboundRateLimit1, + inboundRateLimiterConfig: inboundRateLimit1 + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: nonEvmChainSelector, + remotePoolAddresses: nonEvmRemotePools, + remoteTokenAddress: nonEvmRemoteToken, + outboundRateLimiterConfig: outboundRateLimit2, + inboundRateLimiterConfig: inboundRateLimit2 + }); + + // Assert configuration is applied + vm.expectEmit(); + emit TokenPool.ChainAdded( + chainUpdates[0].remoteChainSelector, + chainUpdates[0].remoteTokenAddress, + chainUpdates[0].outboundRateLimiterConfig, + chainUpdates[0].inboundRateLimiterConfig + ); + vm.expectEmit(); + emit TokenPool.ChainAdded( + chainUpdates[1].remoteChainSelector, + chainUpdates[1].remoteTokenAddress, + chainUpdates[1].outboundRateLimiterConfig, + chainUpdates[1].inboundRateLimiterConfig + ); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + // on1: rateLimit1, on2: rateLimit2, off1: rateLimit1, off2: rateLimit3 + assertState(chainUpdates); + + // Removing an non-existent chain should revert + uint64 strangerChainSelector = 120938; + + uint64[] memory chainRemoves = new uint64[](1); + chainRemoves[0] = strangerChainSelector; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, strangerChainSelector)); + s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + // State remains + assertState(chainUpdates); + + // Can remove a chain + chainRemoves[0] = evmChainSelector; + + vm.expectEmit(); + emit TokenPool.ChainRemoved(chainRemoves[0]); + + s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + + // State updated, only chain 2 remains + TokenPool.ChainUpdate[] memory singleChainConfigured = new TokenPool.ChainUpdate[](1); + singleChainConfigured[0] = chainUpdates[1]; + assertState(singleChainConfigured); + + // Cannot reset already configured ramp + vm.expectRevert( + abi.encodeWithSelector(TokenPool.ChainAlreadyExists.selector, singleChainConfigured[0].remoteChainSelector) + ); + s_tokenPool.applyChainUpdates(new uint64[](0), singleChainConfigured); + } + + function test_applyChainUpdates_UpdatesRemotePoolHashes() public { + assertEq(s_tokenPool.getRemotePools(DEST_CHAIN_SELECTOR).length, 0); + + uint64 selector1 = 789; + uint64 selector2 = 123; + uint64 selector3 = 456; + + bytes memory pool1 = abi.encode(makeAddr("pool1")); + bytes memory pool2 = abi.encode(makeAddr("pool2")); + bytes memory pool3 = abi.encode(makeAddr("pool3")); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](3); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: selector1, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: pool1, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: selector2, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: pool2, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[2] = TokenPool.ChainUpdate({ + remoteChainSelector: selector3, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: pool3, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + // This adds 3 for the first chain, 2 for the second, and 1 for the third for a total of 6. + for (uint256 i = 0; i < chainUpdates.length; ++i) { + for (uint256 j = i; j < chainUpdates.length; ++j) { + s_tokenPool.addRemotePool(chainUpdates[i].remoteChainSelector, abi.encode(i, j)); + } + assertEq(s_tokenPool.getRemotePools(chainUpdates[i].remoteChainSelector).length, 3 - i); + } + + // Removing a chain should remove all associated pool hashes + uint64[] memory chainRemoves = new uint64[](1); + chainRemoves[0] = selector1; + + s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + + assertEq(s_tokenPool.getRemotePools(selector1).length, 0); + + chainRemoves[0] = selector2; + + s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + + assertEq(s_tokenPool.getRemotePools(selector2).length, 0); + + // The above deletions should not have affected the third chain + assertEq(s_tokenPool.getRemotePools(selector3).length, 1); + } + + // Reverts + + function test_applyChainUpdates_OnlyCallableByOwner_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); + s_tokenPool.applyChainUpdates(new uint64[](0), new TokenPool.ChainUpdate[](0)); + } + + function test_applyChainUpdates_ZeroAddressNotAllowed_Revert() public { + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = ""; + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) + }); + + vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: 1, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: "", + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e28, rate: 1e18}) + }); + + vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + } + + function test_applyChainUpdates_NonExistentChain_Revert() public { + uint64[] memory chainRemoves = new uint64[](1); + chainRemoves[0] = 1; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainRemoves[0])); + s_tokenPool.applyChainUpdates(chainRemoves, new TokenPool.ChainUpdate[](0)); + } + + function test_applyChainUpdates_InvalidRateLimitRate_Revert() public { + uint64 unusedChainSelector = 2 ** 64 - 1; + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: unusedChainSelector, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 0, rate: 0}), + inboundRateLimiterConfig: RateLimiter.Config({isEnabled: true, capacity: 100e22, rate: 1e12}) + }); + + // Outbound + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + chainUpdates[0].outboundRateLimiterConfig.rate = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + chainUpdates[0].outboundRateLimiterConfig.capacity = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].outboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + chainUpdates[0].outboundRateLimiterConfig.capacity = 101; + + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + // Change the chain selector as adding the same one would revert + chainUpdates[0].remoteChainSelector = unusedChainSelector - 1; + + // Inbound + + chainUpdates[0].inboundRateLimiterConfig.capacity = 0; + chainUpdates[0].inboundRateLimiterConfig.rate = 0; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + chainUpdates[0].inboundRateLimiterConfig.rate = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + chainUpdates[0].inboundRateLimiterConfig.capacity = 100; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.InvalidRateLimitRate.selector, chainUpdates[0].inboundRateLimiterConfig) + ); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + chainUpdates[0].inboundRateLimiterConfig.capacity = 101; + + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol new file mode 100644 index 0000000000..4262fac221 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.calculateLocalAmount.t.sol @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +import {IERC20Metadata} from + "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +contract TokenPool_calculateLocalAmount is TokenPoolSetup { + function test_calculateLocalAmount() public view { + uint8 localDecimals = s_tokenPool.getTokenDecimals(); + uint256 remoteAmount = 123e18; + + // Zero decimals should return amount * 10^localDecimals + assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, 0), remoteAmount * 10 ** localDecimals); + + // Equal decimals should return the same amount + assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, localDecimals), remoteAmount); + + // Remote amount with more decimals should return less local amount + uint256 expectedAmount = remoteAmount; + for (uint8 remoteDecimals = localDecimals + 1; remoteDecimals < 36; ++remoteDecimals) { + expectedAmount /= 10; + assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals), expectedAmount); + } + + // Remote amount with less decimals should return more local amount + expectedAmount = remoteAmount; + for (uint8 remoteDecimals = localDecimals - 1; remoteDecimals > 0; --remoteDecimals) { + expectedAmount *= 10; + assertEq(s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals), expectedAmount); + } + } + + // Reverts + + function test_calculateLocalAmount_RevertWhen_LowRemoteDecimalsOverflows() public { + uint8 remoteDecimals = 0; + uint8 localDecimals = 78; + uint256 remoteAmount = 1; + + vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); + + s_tokenPool = + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } + + function test_calculateLocalAmount_RevertWhen_HighLocalDecimalsOverflows() public { + uint8 remoteDecimals = 18; + uint8 localDecimals = 18 + 78; + uint256 remoteAmount = 1; + + vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); + + s_tokenPool = + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } + + function test_calculateLocalAmount_RevertWhen_HighRemoteDecimalsOverflows() public { + uint8 remoteDecimals = 18 + 78; + uint8 localDecimals = 18; + uint256 remoteAmount = 1; + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } + + function test_calculateLocalAmount_RevertWhen_HighAmountOverflows() public { + uint8 remoteDecimals = 18; + uint8 localDecimals = 18 + 28; + uint256 remoteAmount = 1e50; + + vm.mockCall(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(localDecimals)); + + s_tokenPool = + new TokenPoolHelper(s_token, localDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.OverflowDetected.selector, remoteDecimals, localDecimals, remoteAmount) + ); + + s_tokenPool.calculateLocalAmount(remoteAmount, remoteDecimals); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol new file mode 100644 index 0000000000..4b643d66b9 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.constructor.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata} from + "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +contract TokenPool_constructor is TokenPoolSetup { + function test_constructor() public view { + assertEq(address(s_token), address(s_tokenPool.getToken())); + assertEq(address(s_mockRMN), s_tokenPool.getRmnProxy()); + assertFalse(s_tokenPool.getAllowListEnabled()); + assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); + assertEq(DEFAULT_TOKEN_DECIMALS, s_tokenPool.getTokenDecimals()); + } + + function test_constructor_DecimalCallFails() public { + uint8 decimals = 255; + + vm.mockCallRevert(address(s_token), abi.encodeWithSelector(IERC20Metadata.decimals.selector), "decimals fails"); + + s_tokenPool = new TokenPoolHelper(s_token, decimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + + assertEq(s_tokenPool.getTokenDecimals(), decimals); + } + + // Reverts + + function test_constructor_RevertWhen_ZeroAddressNotAllowed() public { + vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); + + s_tokenPool = new TokenPoolHelper( + IERC20(address(0)), DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + } + + function test_constructor_RevertWhen_InvalidDecimalArgs() public { + uint8 invalidDecimals = DEFAULT_TOKEN_DECIMALS + 1; + + vm.expectRevert( + abi.encodeWithSelector(TokenPool.InvalidDecimalArgs.selector, invalidDecimals, DEFAULT_TOKEN_DECIMALS) + ); + + s_tokenPool = + new TokenPoolHelper(s_token, invalidDecimals, new address[](0), address(s_mockRMN), address(s_sourceRouter)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol new file mode 100644 index 0000000000..8d4256d347 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowList.t.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; + +contract TokenPoolWithAllowList_getAllowList is TokenPoolWithAllowListSetup { + function test_GetAllowList_Success() public view { + address[] memory setAddresses = s_tokenPool.getAllowList(); + assertEq(2, setAddresses.length); + assertEq(s_allowedSenders[0], setAddresses[0]); + assertEq(s_allowedSenders[1], setAddresses[1]); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol new file mode 100644 index 0000000000..2a36a84699 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getAllowListEnabled.t.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; + +contract TokenPoolWithAllowList_getAllowListEnabled is TokenPoolWithAllowListSetup { + function test_GetAllowListEnabled_Success() public view { + assertTrue(s_tokenPool.getAllowListEnabled()); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol new file mode 100644 index 0000000000..5e619aede4 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.getRemotePool.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_getRemotePool is TokenPoolSetup { + function test_getRemotePools() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; + bytes memory remotePool = abi.encode(makeAddr("remotePool")); + bytes memory remoteToken = abi.encode(makeAddr("remoteToken")); + + // Zero indicates nothing is set + assertEq(0, s_tokenPool.getRemotePools(chainSelector).length); + + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = remotePool; + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: remoteToken, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + bytes[] memory remotePools = s_tokenPool.getRemotePools(chainSelector); + assertEq(1, remotePools.length); + assertEq(remotePool, remotePools[0]); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol new file mode 100644 index 0000000000..8df07a285f --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOffRamp.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Router} from "../../../Router.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_onlyOffRamp is TokenPoolSetup { + function test_onlyOffRamp_Success() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + address offRamp = makeAddr("onRamp"); + + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); + + vm.startPrank(offRamp); + + s_tokenPool.onlyOffRampModifier(chainSelector); + } + + function test_ChainNotAllowed_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; + address offRamp = makeAddr("onRamp"); + + vm.startPrank(offRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOffRampModifier(chainSelector); + + vm.startPrank(OWNER); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: chainSelector, offRamp: offRamp}); + s_sourceRouter.applyRampUpdates(new Router.OnRamp[](0), new Router.OffRamp[](0), offRampUpdates); + + vm.startPrank(offRamp); + // Should succeed now that we've added the chain + s_tokenPool.onlyOffRampModifier(chainSelector); + + uint64[] memory chainsToRemove = new uint64[](1); + chainsToRemove[0] = chainSelector; + + vm.startPrank(OWNER); + s_tokenPool.applyChainUpdates(chainsToRemove, new TokenPool.ChainUpdate[](0)); + + vm.startPrank(offRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOffRampModifier(chainSelector); + } + + function test_CallerIsNotARampOnRouter_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + address offRamp = makeAddr("offRamp"); + + vm.startPrank(offRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, offRamp)); + + s_tokenPool.onlyOffRampModifier(chainSelector); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol new file mode 100644 index 0000000000..be0c21e4c1 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.onlyOnRamp.t.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Router} from "../../../Router.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_onlyOnRamp is TokenPoolSetup { + function test_onlyOnRamp_Success() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + address onRamp = makeAddr("onRamp"); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + vm.startPrank(onRamp); + + s_tokenPool.onlyOnRampModifier(chainSelector); + } + + function test_ChainNotAllowed_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; + address onRamp = makeAddr("onRamp"); + + vm.startPrank(onRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOnRampModifier(chainSelector); + + vm.startPrank(OWNER); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: chainSelector, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: chainSelector, onRamp: onRamp}); + s_sourceRouter.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + vm.startPrank(onRamp); + // Should succeed now that we've added the chain + s_tokenPool.onlyOnRampModifier(chainSelector); + + uint64[] memory chainsToRemove = new uint64[](1); + chainsToRemove[0] = chainSelector; + + vm.startPrank(OWNER); + s_tokenPool.applyChainUpdates(chainsToRemove, new TokenPool.ChainUpdate[](0)); + + vm.startPrank(onRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.ChainNotAllowed.selector, chainSelector)); + s_tokenPool.onlyOffRampModifier(chainSelector); + } + + function test_CallerIsNotARampOnRouter_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + address onRamp = makeAddr("onRamp"); + + vm.startPrank(onRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, onRamp)); + + s_tokenPool.onlyOnRampModifier(chainSelector); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol new file mode 100644 index 0000000000..9817fe227e --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.parseRemoteDecimals.t.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_parseRemoteDecimals is TokenPoolSetup { + function test_parseRemoteDecimals() public view { + uint256 remoteDecimals = 12; + bytes memory encodedDecimals = abi.encode(remoteDecimals); + + assertEq(s_tokenPool.parseRemoteDecimals(encodedDecimals), remoteDecimals); + + assertEq(s_tokenPool.parseRemoteDecimals(s_tokenPool.encodeLocalDecimals()), s_tokenPool.getTokenDecimals()); + } + + function test_parseRemoteDecimals_NoDecimalsDefaultsToLocalDecimals() public view { + assertEq(s_tokenPool.parseRemoteDecimals(""), s_tokenPool.getTokenDecimals()); + } + + function test_parseRemoteDecimals_RevertWhen_InvalidRemoteChainDecimals_DigitTooLarge() public { + bytes memory encodedDecimals = abi.encode(uint256(256)); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemoteChainDecimals.selector, encodedDecimals)); + + s_tokenPool.parseRemoteDecimals(encodedDecimals); + } + + function test_parseRemoteDecimals_RevertWhen_InvalidRemoteChainDecimals_WrongType() public { + bytes memory encodedDecimals = abi.encode(uint256(256), "wrong type"); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemoteChainDecimals.selector, encodedDecimals)); + + s_tokenPool.parseRemoteDecimals(encodedDecimals); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol new file mode 100644 index 0000000000..2fa9ef1662 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.removeRemotePool.t.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_removeRemotePool is TokenPoolSetup { + function test_removeRemotePool_Success() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + // Use a longer data type to ensure it also works for non-evm + bytes memory remotePool = abi.encode(makeAddr("non-evm-1"), makeAddr("non-evm-2")); + + vm.expectEmit(); + emit TokenPool.RemotePoolAdded(chainSelector, remotePool); + + // Add the remote pool properly so that it can be removed + s_tokenPool.addRemotePool(chainSelector, remotePool); + + bytes[] memory remotePools = s_tokenPool.getRemotePools(chainSelector); + assertEq(remotePools.length, 2); + assertEq(remotePools[0], abi.encode(s_initialRemotePool)); + assertEq(remotePools[1], remotePool); + + vm.expectEmit(); + emit TokenPool.RemotePoolRemoved(chainSelector, remotePool); + + s_tokenPool.removeRemotePool(chainSelector, remotePool); + + remotePools = s_tokenPool.getRemotePools(chainSelector); + assertEq(remotePools.length, 1); + assertEq(remotePools[0], abi.encode(s_initialRemotePool)); + + // Assert that it can be added after it has been removed + s_tokenPool.addRemotePool(chainSelector, remotePool); + + remotePools = s_tokenPool.getRemotePools(chainSelector); + assertEq(remotePools.length, 2); + assertEq(remotePools[0], abi.encode(s_initialRemotePool)); + assertEq(remotePools[1], remotePool); + } + + // Reverts + + function test_NonExistentChain_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR + 1; + bytes memory remotePool = abi.encode(type(uint256).max); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, chainSelector)); + + s_tokenPool.removeRemotePool(chainSelector, remotePool); + } + + function test_InvalidRemotePoolForChain_Revert() public { + uint64 chainSelector = DEST_CHAIN_SELECTOR; + bytes memory remotePool = abi.encode(type(uint256).max); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.InvalidRemotePoolForChain.selector, chainSelector, remotePool)); + + s_tokenPool.removeRemotePool(chainSelector, remotePool); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol new file mode 100644 index 0000000000..4dea9bf403 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setChainRateLimiterConfig.t.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {RateLimiter} from "../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_setChainRateLimiterConfig is TokenPoolSetup { + function testFuzz_SetChainRateLimiterConfig_Success(uint128 capacity, uint128 rate, uint32 newTime) public { + // Cap the lower bound to 4 so 4/2 is still >= 2 + vm.assume(capacity >= 4); + // Cap the lower bound to 2 so 2/2 is still >= 1 + rate = uint128(bound(rate, 2, capacity - 2)); + // Bucket updates only work on increasing time + newTime = uint32(bound(newTime, block.timestamp + 1, type(uint32).max)); + vm.warp(newTime); + + uint256 oldOutboundTokens = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; + uint256 oldInboundTokens = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR).tokens; + + RateLimiter.Config memory newOutboundConfig = RateLimiter.Config({isEnabled: true, capacity: capacity, rate: rate}); + RateLimiter.Config memory newInboundConfig = + RateLimiter.Config({isEnabled: true, capacity: capacity / 2, rate: rate / 2}); + + vm.expectEmit(); + emit RateLimiter.ConfigChanged(newOutboundConfig); + vm.expectEmit(); + emit RateLimiter.ConfigChanged(newInboundConfig); + vm.expectEmit(); + emit TokenPool.ChainConfigured(DEST_CHAIN_SELECTOR, newOutboundConfig, newInboundConfig); + + s_tokenPool.setChainRateLimiterConfig(DEST_CHAIN_SELECTOR, newOutboundConfig, newInboundConfig); + + uint256 expectedTokens = RateLimiter._min(newOutboundConfig.capacity, oldOutboundTokens); + + RateLimiter.TokenBucket memory bucket = s_tokenPool.getCurrentOutboundRateLimiterState(DEST_CHAIN_SELECTOR); + assertEq(bucket.capacity, newOutboundConfig.capacity); + assertEq(bucket.rate, newOutboundConfig.rate); + assertEq(bucket.tokens, expectedTokens); + assertEq(bucket.lastUpdated, newTime); + + expectedTokens = RateLimiter._min(newInboundConfig.capacity, oldInboundTokens); + + bucket = s_tokenPool.getCurrentInboundRateLimiterState(DEST_CHAIN_SELECTOR); + assertEq(bucket.capacity, newInboundConfig.capacity); + assertEq(bucket.rate, newInboundConfig.rate); + assertEq(bucket.tokens, expectedTokens); + assertEq(bucket.lastUpdated, newTime); + } + + // Reverts + + function test_OnlyOwnerOrRateLimitAdmin_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, STRANGER)); + s_tokenPool.setChainRateLimiterConfig( + DEST_CHAIN_SELECTOR, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() + ); + } + + function test_NonExistentChain_Revert() public { + uint64 wrongChainSelector = 9084102894; + + vm.expectRevert(abi.encodeWithSelector(TokenPool.NonExistentChain.selector, wrongChainSelector)); + s_tokenPool.setChainRateLimiterConfig( + wrongChainSelector, _getOutboundRateLimiterConfig(), _getInboundRateLimiterConfig() + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol new file mode 100644 index 0000000000..7c57741cf4 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRateLimitAdmin.t.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Ownable2Step} from "../../../../shared/access/Ownable2Step.sol"; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPool_setRateLimitAdmin is TokenPoolSetup { + function test_SetRateLimitAdmin_Success() public { + assertEq(address(0), s_tokenPool.getRateLimitAdmin()); + vm.expectEmit(); + emit TokenPool.RateLimitAdminSet(OWNER); + s_tokenPool.setRateLimitAdmin(OWNER); + assertEq(OWNER, s_tokenPool.getRateLimitAdmin()); + } + + // Reverts + + function test_SetRateLimitAdmin_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); + s_tokenPool.setRateLimitAdmin(STRANGER); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol new file mode 100644 index 0000000000..4bf85f3af9 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPool.setRouter.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolWithAllowListSetup} from "./TokenPoolWithAllowListSetup.t.sol"; + +contract TokenPoolWithAllowList_setRouter is TokenPoolWithAllowListSetup { + function test_SetRouter_Success() public { + assertEq(address(s_sourceRouter), s_tokenPool.getRouter()); + + address newRouter = makeAddr("newRouter"); + + vm.expectEmit(); + emit TokenPool.RouterUpdated(address(s_sourceRouter), newRouter); + + s_tokenPool.setRouter(newRouter); + + assertEq(newRouter, s_tokenPool.getRouter()); + } + + // Reverts + + function test_ZeroAddressNotAllowed_Revert() public { + address newRouter = address(0); + + vm.expectRevert(TokenPool.ZeroAddressNotAllowed.selector); + + s_tokenPool.setRouter(newRouter); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol new file mode 100644 index 0000000000..e743b950c2 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolSetup.t.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../shared/token/ERC20/BurnMintERC20.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; +import {RouterSetup} from "../../router/RouterSetup.t.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +contract TokenPoolSetup is RouterSetup { + IERC20 internal s_token; + TokenPoolHelper internal s_tokenPool; + + address internal s_initialRemotePool = makeAddr("initialRemotePool"); + address internal s_initialRemoteToken = makeAddr("initialRemoteToken"); + + function setUp() public virtual override { + RouterSetup.setUp(); + s_token = new BurnMintERC20("LINK", "LNK", 18, 0, 0); + deal(address(s_token), OWNER, type(uint256).max); + + s_tokenPool = new TokenPoolHelper( + s_token, DEFAULT_TOKEN_DECIMALS, new address[](0), address(s_mockRMN), address(s_sourceRouter) + ); + + bytes[] memory remotePoolAddresses = new bytes[](1); + remotePoolAddresses[0] = abi.encode(s_initialRemotePool); + + TokenPool.ChainUpdate[] memory chainUpdate = new TokenPool.ChainUpdate[](1); + chainUpdate[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddresses: remotePoolAddresses, + remoteTokenAddress: abi.encode(s_initialRemoteToken), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + s_tokenPool.applyChainUpdates(new uint64[](0), chainUpdate); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol new file mode 100644 index 0000000000..478e899637 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/TokenPool/TokenPoolWithAllowListSetup.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPoolHelper} from "../../helpers/TokenPoolHelper.sol"; +import {TokenPoolSetup} from "./TokenPoolSetup.t.sol"; + +contract TokenPoolWithAllowListSetup is TokenPoolSetup { + address[] internal s_allowedSenders; + + function setUp() public virtual override { + TokenPoolSetup.setUp(); + + s_allowedSenders.push(STRANGER); + s_allowedSenders.push(OWNER); + + s_tokenPool = new TokenPoolHelper( + s_token, DEFAULT_TOKEN_DECIMALS, s_allowedSenders, address(s_mockRMN), address(s_sourceRouter) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol new file mode 100644 index 0000000000..394357f213 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITokenMessenger} from "../../../../pools/USDC/ITokenMessenger.sol"; + +import {Pool} from "../../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; + +contract HybridLockReleaseUSDCTokenPool_lockOrBurn is HybridLockReleaseUSDCTokenPoolSetup { + function test_onLockReleaseMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + } + + function test_PrimaryMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + uint256 amount = 1; + + vm.startPrank(OWNER); + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + receiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + } + + function test_onLockReleaseMechanism_thenSwitchToPrimary_Success() public { + // Test Enabling the LR mechanism and sending an outgoing message + test_PrimaryMechanism_Success(); + + // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message + uint64[] memory destChainRemoves = new uint64[](1); + destChainRemoves[0] = DEST_CHAIN_SELECTOR; + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); + + // Send an outgoing message + test_PrimaryMechanism_Success(); + } + + function test_WhileMigrationPause_Revert() public { + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + // Create a fake migration proposal + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), DEST_CHAIN_SELECTOR); + + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + // Expect the lockOrBurn to fail because a pending CCTP-Migration has paused outgoing messages on CCIP + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol new file mode 100644 index 0000000000..ea3c581ea5 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../../../libraries/Internal.sol"; +import {Pool} from "../../../../libraries/Pool.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {LOCK_RELEASE_FLAG} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; + +contract HybridLockReleaseUSDCTokenPool_releaseOrMint is HybridLockReleaseUSDCTokenPoolSetup { + function test_OnLockReleaseMechanism_Success() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e12; + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(LOCK_RELEASE_FLAG), + offchainTokenData: "" + }) + ); + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + + // Simulate the off-ramp forwarding tokens to the recipient on destination chain + // s_token.transfer(recipient, amount); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + liquidityAmount - amount, + "Incorrect remaining liquidity in TokenPool" + ); + assertEq(s_token.balanceOf(recipient), amount, "Tokens not transferred to recipient"); + } + + // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 + function test_incomingMessageWithPrimaryMechanism() public { + bytes memory encodedUsdcMessage = + hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; + bytes memory attestation = bytes("attestation bytes"); + + uint32 nonce = 4730; + uint32 sourceDomain = 3; + uint256 amount = 100; + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + function test_WhileMigrationPause_Revert() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(SOURCE_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory sourcePoolDataLockRelease = abi.encode(LOCK_RELEASE_FLAG); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + // Expect revert because the lane is paused and no incoming messages should be allowed + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, SOURCE_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourcePoolDataLockRelease, + offchainTokenData: "" + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol new file mode 100644 index 0000000000..4e5a45a143 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.transferLiquidity.t.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; + +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./HybridLockReleaseUSDCTokenPoolSetup.t.sol"; + +contract HybridLockReleaseUSDCTokenPool_TransferLiquidity is HybridLockReleaseUSDCTokenPoolSetup { + function test_transferLiquidity_Success() public { + // Set as the OWNER so we can provide liquidity + vm.startPrank(OWNER); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e9; + + // Provide some liquidity to the pool + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Set the new token pool as the rebalancer + s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); + + vm.expectEmit(); + emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPoolTransferLiquidity), liquidityAmount); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( + address(s_usdcTokenPool), DEST_CHAIN_SELECTOR, liquidityAmount + ); + + s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.owner(), + address(s_usdcTokenPoolTransferLiquidity), + "Ownership of the old pool should be transferred to the new pool" + ); + + assertEq( + s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + liquidityAmount, + "Tokens locked for dest chain doesn't match expected amount in storage" + ); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" + ); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPoolTransferLiquidity)), + liquidityAmount, + "Liquidity amount of tokens should be new in new pool, but aren't" + ); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + 0, + "Liquidity amount of tokens should be zero in old pool, but aren't" + ); + } + + function test_cannotTransferLiquidityDuringPendingMigration_Revert() public { + // Set as the OWNER so we can provide liquidity + vm.startPrank(OWNER); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e9; + + // Provide some liquidity to the pool + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Set the new token pool as the rebalancer + s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + + s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol new file mode 100644 index 0000000000..9b318b782c --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPoolSetup.t.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {BurnMintERC677} from "../../../../../shared/token/ERC677/BurnMintERC677.sol"; + +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {USDCSetup} from "../USDCSetup.t.sol"; + +contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + super.setUp(); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + BurnMintERC677(address(s_token)).grantMintAndBurnRoles(address(s_usdcTokenPool)); + + _poolApplyChainUpdates(address(s_usdcTokenPool)); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol new file mode 100644 index 0000000000..52ddb9dad4 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.burnLockedUSDC.t.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Pool} from "../../../../libraries/Pool.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; +import {HybridLockReleaseUSDCTokenPool_lockOrBurn} from + "../HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.lockOrBurn.t.sol"; + +contract USDCBridgeMigrator_BurnLockedUSDC is HybridLockReleaseUSDCTokenPool_lockOrBurn { + function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + // Ensure that the tokens are properly locked + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + amount, + "Internal locked token accounting is incorrect" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CircleMigratorAddressSet(CIRCLE); + + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "Current proposed chain migration does not match expected for DEST_CHAIN_SELECTOR" + ); + + // Impersonate the set circle address and execute the proposal + vm.startPrank(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationExecuted(DEST_CHAIN_SELECTOR, amount); + + // Ensure the call to the burn function is properly + vm.expectCall(address(s_token), abi.encodeWithSelector(bytes4(keccak256("burn(uint256)")), amount)); + + s_usdcTokenPool.burnLockedUSDC(); + + // Assert that the tokens were actually burned + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens were not burned out of the tokenPool"); + + // Ensure the proposal slot was cleared and there's no tokens locked for the destination chain anymore + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), 0, "Proposal Slot should be empty"); + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "No tokens should be locked for DEST_CHAIN_SELECTOR after CCTP-approved burn" + ); + + assertFalse( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" + ); + + test_PrimaryMechanism_Success(); + } + + function test_invalidPermissions_Revert() public { + address CIRCLE = makeAddr("CIRCLE"); + + vm.startPrank(OWNER); + + // Set the circle migrator address for later, but don't start pranking as it yet + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.onlyCircle.selector)); + + // Should fail because only Circle can call this function + s_usdcTokenPool.burnLockedUSDC(); + + vm.startPrank(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.NoMigrationProposalPending.selector)); + s_usdcTokenPool.burnLockedUSDC(); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol new file mode 100644 index 0000000000..f4f56cba3e --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.cancelMigrationProposal.t.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; + +contract USDCBridgeMigrator_cancelMigrationProposal is HybridLockReleaseUSDCTokenPoolSetup { + function test_cancelExistingCCTPMigrationProposal_Success() public { + vm.startPrank(OWNER); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "migration proposal should exist, but doesn't" + ); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationCancelled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + 0, + "migration proposal exists, but shouldn't after being cancelled" + ); + + vm.expectRevert(USDCBridgeMigrator.NoMigrationProposalPending.selector); + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } + + function test_cannotCancelANonExistentMigrationProposal_Revert() public { + vm.expectRevert(USDCBridgeMigrator.NoMigrationProposalPending.selector); + + // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol new file mode 100644 index 0000000000..855db7c5c6 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.excludeTokensFromBurn.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; + +contract USDCBridgeMigrator_excludeTokensFromBurn is HybridLockReleaseUSDCTokenPoolSetup { + function test_excludeTokensWhenNoMigrationProposalPending_Revert() public { + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.NoMigrationProposalPending.selector)); + + vm.startPrank(OWNER); + + s_usdcTokenPool.excludeTokensFromBurn(SOURCE_CHAIN_SELECTOR, 1e6); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol new file mode 100644 index 0000000000..b2668bde80 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.proposeMigration.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; +import {HybridLockReleaseUSDCTokenPoolSetup} from "./USDCBridgeMigratorSetup.t.sol"; + +contract USDCBridgeMigrator_proposeMigration is HybridLockReleaseUSDCTokenPoolSetup { + function test_ChainNotUsingLockRelease_Revert() public { + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.InvalidChainSelector.selector)); + + vm.startPrank(OWNER); + + s_usdcTokenPool.proposeCCTPMigration(0x98765); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol new file mode 100644 index 0000000000..88196d8779 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.provideLiquidity.t.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCBridgeMigrator_BurnLockedUSDC} from "./USDCBridgeMigrator.burnLockedUSDC.t.sol"; + +contract USDCBridgeMigrator_provideLiquidity is USDCBridgeMigrator_BurnLockedUSDC { + function test_cannotModifyLiquidityWithoutPermissions_Revert() public { + address randomAddr = makeAddr("RANDOM"); + + vm.startPrank(randomAddr); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); + + // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + } + + function test_cannotProvideLiquidity_AfterMigration_Revert() public { + test_lockOrBurn_then_BurnInCCTPMigration_Success(); + + vm.startPrank(OWNER); + + vm.expectRevert( + abi.encodeWithSelector( + HybridLockReleaseUSDCTokenPool.TokenLockingNotAllowedAfterMigration.selector, DEST_CHAIN_SELECTOR + ) + ); + + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + } + + function test_cannotProvideLiquidityWhenMigrationProposalPending_Revert() public { + vm.startPrank(OWNER); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol new file mode 100644 index 0000000000..40569603e9 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.releaseOrMint.t.sol @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../../../libraries/Internal.sol"; +import {Pool} from "../../../../libraries/Pool.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {LOCK_RELEASE_FLAG} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCBridgeMigrator} from "../../../../pools/USDC/USDCBridgeMigrator.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool_releaseOrMint} from + "../HybridLockReleaseUSDCTokenPool/HybridLockReleaseUSDCTokenPool.releaseOrMint.t.sol"; + +contract USDCBridgeMigrator_releaseOrMint is HybridLockReleaseUSDCTokenPool_releaseOrMint { + function test_unstickManualTxAfterMigration_destChain_Success() public { + address recipient = address(1234); + // Test the edge case where a tx is stuck in the manual tx queue and the destination chain is the one that + // should process is after a migration. I.E the message will have the Lock-Release flag set in the OffChainData, + // which should tell it to use the lock-release mechanism with the tokens provided. + + // We want the released amount to be 1e6, so to simulate the workflow, we sent those tokens to the contract as + // liquidity + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount); + + // By Default, the source chain will be indicated as use-CCTP so we need to change that. We create a message + // that will use the Lock-Release flag in the offchain data to indicate that the tokens should be released + // instead of minted since there's no attestation for us to use. + + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(LOCK_RELEASE_FLAG), + offchainTokenData: "" + }) + ); + + // By this point, the tx should have executed, with the Lock-Release taking over, and being forwaded to the + // recipient + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + // which after a migration will mean all new messages. + + // The message should fail without an error because it failed to decode a non-existent attestation which would + // revert without an error + vm.expectRevert(); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: "", + offchainTokenData: "" + }) + ); + } + + function test_unstickManualTxAfterMigration_homeChain_Success() public { + address CIRCLE = makeAddr("CIRCLE"); + address recipient = address(1234); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + // Test the edge case where a tx is stuck in the manual tx queue and the source chain (mainnet) needs unsticking + // In this test we want 1e6 worth of tokens to be stuck, so first we provide liquidity to the pool >1e6 + + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + // I picked 3x the amount to be stuck so that we can have enough to release with a buffer + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount * 3); + + // At this point in the process, the router will lock new messages, so we want to simulate excluding tokens + // stuck coming back from the destination, to the home chain. This way they can be released and not minted + // since there's no corresponding attestation to use for minting. + vm.startPrank(OWNER); + + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + // Exclude the tokens from being burned and check for the event + vm.expectEmit(); + emit USDCBridgeMigrator.TokensExcludedFromBurn(SOURCE_CHAIN_SELECTOR, amount, (amount * 3) - amount); + + s_usdcTokenPool.excludeTokensFromBurn(SOURCE_CHAIN_SELECTOR, amount); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), + (amount * 3), + "Tokens locked minus ones excluded from the burn should be 2e6" + ); + + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "1e6 tokens should be excluded from the burn" + ); + + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.startPrank(CIRCLE); + + s_usdcTokenPool.burnLockedUSDC(); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), 0, "All tokens should be burned out of the pool" + ); + + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "There should still be 1e6 tokens excluded from the burn" + ); + + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 1e6, "All tokens minus the excluded should be in the pool"); + + // Now that the burn is successful, we can release the tokens that were excluded from the burn + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(LOCK_RELEASE_FLAG), + offchainTokenData: "" + }) + ); + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 0, + "All tokens should be released from the exclusion list" + ); + + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + test_incomingMessageWithPrimaryMechanism(); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol new file mode 100644 index 0000000000..9db74061a3 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigrator.updateChainSelectorMechanism.t.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; + +import {USDCBridgeMigrator_BurnLockedUSDC} from "./USDCBridgeMigrator.burnLockedUSDC.t.sol"; + +contract USDCBridgeMigrator_updateChainSelectorMechanism is USDCBridgeMigrator_BurnLockedUSDC { + function test_cannotRevertChainMechanism_afterMigration_Revert() public { + test_lockOrBurn_then_BurnInCCTPMigration_Success(); + + vm.startPrank(OWNER); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + vm.expectRevert( + abi.encodeWithSelector( + HybridLockReleaseUSDCTokenPool.TokenLockingNotAllowedAfterMigration.selector, DEST_CHAIN_SELECTOR + ) + ); + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol new file mode 100644 index 0000000000..5a250fd16a --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCBridgeMigrator/USDCBridgeMigratorSetup.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {HybridLockReleaseUSDCTokenPool} from "../../../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCSetup} from "../USDCSetup.t.sol"; + +contract HybridLockReleaseUSDCTokenPoolSetup is USDCSetup { + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + + function setUp() public virtual override { + super.setUp(); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol new file mode 100644 index 0000000000..9ec89b5258 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCSetup.t.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC677} from "../../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../../Router.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; + +import {BaseTest} from "../../BaseTest.t.sol"; +import {MockE2EUSDCTransmitter} from "../../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../../mocks/MockUSDCTokenMessenger.sol"; + +contract USDCSetup is BaseTest { + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant USDC_DEST_TOKEN_GAS = 180_000; + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + IBurnMintERC20 internal s_token; + + function setUp() public virtual override { + super.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("USD Coin", "USDC", 6, 0); + s_token = usdcToken; + + deal(address(s_token), OWNER, type(uint256).max); + _setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + } + + function _poolApplyChainUpdates( + address pool + ) internal { + bytes[] memory sourcePoolAddresses = new bytes[](1); + sourcePoolAddresses[0] = abi.encode(SOURCE_CHAIN_USDC_POOL); + + bytes[] memory destPoolAddresses = new bytes[](1); + destPoolAddresses[0] = abi.encode(DEST_CHAIN_USDC_POOL); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddresses: sourcePoolAddresses, + remoteTokenAddress: abi.encode(address(s_token)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddresses: destPoolAddresses, + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + TokenPool(pool).applyChainUpdates(new uint64[](0), chainUpdates); + } + + function _setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage( + USDCMessage memory usdcMessage + ) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol new file mode 100644 index 0000000000..03d328b8e8 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.lockOrBurn.t.sol @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ITokenMessenger} from "../../../../pools/USDC/ITokenMessenger.sol"; + +import {Router} from "../../../../Router.sol"; +import {Pool} from "../../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; + +contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { + // Base test case, included for PR gas comparisons as fuzz tests are excluded from forge snapshot due to being flaky. + function test_LockOrBurn_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + uint256 amount = 1; + s_token.transfer(address(s_usdcTokenPool), amount); + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + receiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + } + + function testFuzz_LockOrBurn_Success(bytes32 destinationReceiver, uint256 amount) public { + vm.assume(destinationReceiver != bytes32(0)); + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); + s_token.transfer(address(s_usdcTokenPool), amount); + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + destinationReceiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(destinationReceiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); + } + + function testFuzz_LockOrBurnWithAllowList_Success(bytes32 destinationReceiver, uint256 amount) public { + vm.assume(destinationReceiver != bytes32(0)); + amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); + s_token.transfer(address(s_usdcTokenPoolWithAllowList), amount); + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPoolWithAllowList.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPoolWithAllowList), + destinationReceiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: s_allowedList[0], + receiver: abi.encodePacked(destinationReceiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); + } + + // Reverts + function test_UnknownDomain_Revert() public { + uint64 wrongDomain = DEST_CHAIN_SELECTOR + 1; + // We need to setup the wrong chainSelector so it reaches the domain check + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: wrongDomain, onRamp: s_routerAllowedOnRamp}); + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: wrongDomain, + remotePoolAddresses: new bytes[](0), + remoteTokenAddress: abi.encode(address(2)), + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(new uint64[](0), chainUpdates); + + uint256 amount = 1000; + vm.startPrank(s_routerAllowedOnRamp); + deal(address(s_token), s_routerAllowedOnRamp, amount); + s_token.approve(address(s_usdcTokenPool), amount); + + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.UnknownDomain.selector, wrongDomain)); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(address(0)), + amount: amount, + remoteChainSelector: wrongDomain, + localToken: address(s_token) + }) + ); + } + + function test_CallerIsNotARampOnRouter_Revert() public { + vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, OWNER)); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(address(0)), + amount: 0, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } + + function test_LockOrBurnWithAllowList_Revert() public { + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); + + s_usdcTokenPoolWithAllowList.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: STRANGER, + receiver: abi.encodePacked(address(0)), + amount: 1000, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol new file mode 100644 index 0000000000..4499c748a6 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.releaseOrMint.t.sol @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../../../libraries/Internal.sol"; +import {Pool} from "../../../../libraries/Pool.sol"; +import {RateLimiter} from "../../../../libraries/RateLimiter.sol"; +import {TokenPool} from "../../../../pools/TokenPool.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {MockE2EUSDCTransmitter} from "../../../mocks/MockE2EUSDCTransmitter.sol"; +import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; + +contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { + // From https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/BurnMessage.sol#L57 + function _formatMessage( + uint32 _version, + bytes32 _burnToken, + bytes32 _mintRecipient, + uint256 _amount, + bytes32 _messageSender + ) internal pure returns (bytes memory) { + return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); + } + + function testFuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { + vm.assume(recipient != address(0) && recipient != address(s_token)); + amount = bound(amount, 0, _getInboundRateLimiterConfig().capacity); + + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: SOURCE_DOMAIN_IDENTIFIER, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: 0x060606060606, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(uint160(recipient))), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: _formatMessage( + 0, + bytes32(uint256(uint160(address(s_token)))), + bytes32(uint256(uint160(recipient))), + amount, + bytes32(uint256(uint160(OWNER))) + ) + }); + + bytes memory message = _generateUSDCMessage(usdcMessage); + bytes memory attestation = bytes("attestation bytes"); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode( + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) + ), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: message, attestation: attestation})); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + vm.expectEmit(); + emit TokenPool.Minted(s_routerAllowedOffRamp, recipient, amount); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, message, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 + function test_ReleaseOrMintRealTx_Success() public { + bytes memory encodedUsdcMessage = + hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; + bytes memory attestation = bytes("attestation bytes"); + + uint32 nonce = 4730; + uint32 sourceDomain = 3; + uint256 amount = 100; + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + // Reverts + function test_UnlockingUSDCFailed_Revert() public { + vm.startPrank(s_routerAllowedOffRamp); + s_mockUSDCTransmitter.setShouldSucceed(false); + + uint256 amount = 13255235235; + + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: SOURCE_DOMAIN_IDENTIFIER, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: 0x060606060606, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(uint160(address(s_mockUSDC)))), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: _formatMessage( + 0, + bytes32(uint256(uint160(address(s_token)))), + bytes32(uint256(uint160(OWNER))), + amount, + bytes32(uint256(uint160(OWNER))) + ) + }); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode( + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) + ), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory offchainTokenData = abi.encode( + USDCTokenPool.MessageAndAttestation({message: _generateUSDCMessage(usdcMessage), attestation: bytes("")}) + ); + + vm.expectRevert(USDCTokenPool.UnlockingUSDCFailed.selector); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + function test_TokenMaxCapacityExceeded_Revert() public { + uint256 capacity = _getInboundRateLimiterConfig().capacity; + uint256 amount = 10 * capacity; + address recipient = address(1); + vm.startPrank(s_routerAllowedOffRamp); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: bytes(""), attestation: bytes("")})); + + vm.expectRevert( + abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) + ); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol new file mode 100644 index 0000000000..7fcb75fdf3 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.setDomains.t.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Ownable2Step} from "../../../../../shared/access/Ownable2Step.sol"; +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; + +contract USDCTokenPool_setDomains is USDCTokenPoolSetup { + mapping(uint64 destChainSelector => USDCTokenPool.Domain domain) private s_chainToDomain; + + // Setting lower fuzz run as 256 runs was causing differing gas results in snapshot. + /// forge-config: default.fuzz.runs = 32 + /// forge-config: ccip.fuzz.runs = 32 + function testFuzz_SetDomains_Success( + bytes32[5] calldata allowedCallers, + uint32[5] calldata domainIdentifiers, + uint64[5] calldata destChainSelectors + ) public { + uint256 numberOfDomains = allowedCallers.length; + USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](numberOfDomains); + for (uint256 i = 0; i < numberOfDomains; ++i) { + vm.assume(allowedCallers[i] != bytes32(0) && domainIdentifiers[i] != 0 && destChainSelectors[i] != 0); + + domainUpdates[i] = USDCTokenPool.DomainUpdate({ + allowedCaller: allowedCallers[i], + domainIdentifier: domainIdentifiers[i], + destChainSelector: destChainSelectors[i], + enabled: true + }); + + s_chainToDomain[destChainSelectors[i]] = + USDCTokenPool.Domain({domainIdentifier: domainIdentifiers[i], allowedCaller: allowedCallers[i], enabled: true}); + } + + vm.expectEmit(); + emit USDCTokenPool.DomainsSet(domainUpdates); + + s_usdcTokenPool.setDomains(domainUpdates); + + for (uint256 i = 0; i < numberOfDomains; ++i) { + USDCTokenPool.Domain memory expected = s_chainToDomain[destChainSelectors[i]]; + USDCTokenPool.Domain memory got = s_usdcTokenPool.getDomain(destChainSelectors[i]); + assertEq(got.allowedCaller, expected.allowedCaller); + assertEq(got.domainIdentifier, expected.domainIdentifier); + } + } + + // Reverts + + function test_OnlyOwner_Revert() public { + USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](0); + + vm.startPrank(STRANGER); + vm.expectRevert(Ownable2Step.OnlyCallableByOwner.selector); + + s_usdcTokenPool.setDomains(domainUpdates); + } + + function test_InvalidDomain_Revert() public { + bytes32 validCaller = bytes32(uint256(25)); + // Ensure valid domain works + USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](1); + domainUpdates[0] = USDCTokenPool.DomainUpdate({ + allowedCaller: validCaller, + domainIdentifier: 0, // ensures 0 is valid, as this is eth mainnet + destChainSelector: 45690, + enabled: true + }); + + s_usdcTokenPool.setDomains(domainUpdates); + + // Make update invalid on allowedCaller + domainUpdates[0].allowedCaller = bytes32(0); + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); + + s_usdcTokenPool.setDomains(domainUpdates); + + // Make valid again + domainUpdates[0].allowedCaller = validCaller; + + // Make invalid on destChainSelector + domainUpdates[0].destChainSelector = 0; + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); + + s_usdcTokenPool.setDomains(domainUpdates); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol new file mode 100644 index 0000000000..05ac5f0813 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.supportsInterface.t.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IPoolV1} from "../../../../interfaces/IPool.sol"; +import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; + +import {IERC165} from "../../../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; + +contract USDCTokenPool_supportsInterface is USDCTokenPoolSetup { + function test_SupportsInterface_Success() public view { + assertTrue(s_usdcTokenPool.supportsInterface(type(IPoolV1).interfaceId)); + assertTrue(s_usdcTokenPool.supportsInterface(type(IERC165).interfaceId)); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol new file mode 100644 index 0000000000..975368c38b --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPool.validateMessage.t.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {USDCTokenPoolSetup} from "./USDCTokenPoolSetup.t.sol"; + +contract USDCTokenPool__validateMessage is USDCTokenPoolSetup { + function testFuzz_ValidateMessage_Success(uint32 sourceDomain, uint64 nonce) public { + vm.pauseGasMetering(); + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: sourceDomain, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: nonce, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(299999)), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: bytes("") + }); + + bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); + + vm.resumeGasMetering(); + s_usdcTokenPool.validateMessage( + encodedUsdcMessage, USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain}) + ); + } + + // Reverts + + function test_ValidateInvalidMessage_Revert() public { + USDCMessage memory usdcMessage = USDCMessage({ + version: 0, + sourceDomain: 1553252, + destinationDomain: DEST_DOMAIN_IDENTIFIER, + nonce: 387289284924, + sender: SOURCE_CHAIN_TOKEN_SENDER, + recipient: bytes32(uint256(92398429395823)), + destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), + messageBody: bytes("") + }); + + USDCTokenPool.SourceTokenDataPayload memory sourceTokenData = + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}); + + bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); + + s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); + + uint32 expectedSourceDomain = usdcMessage.sourceDomain + 1; + + vm.expectRevert( + abi.encodeWithSelector(USDCTokenPool.InvalidSourceDomain.selector, expectedSourceDomain, usdcMessage.sourceDomain) + ); + s_usdcTokenPool.validateMessage( + encodedUsdcMessage, + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: expectedSourceDomain}) + ); + + uint64 expectedNonce = usdcMessage.nonce + 1; + + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidNonce.selector, expectedNonce, usdcMessage.nonce)); + s_usdcTokenPool.validateMessage( + encodedUsdcMessage, + USDCTokenPool.SourceTokenDataPayload({nonce: expectedNonce, sourceDomain: usdcMessage.sourceDomain}) + ); + + usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER + 1; + vm.expectRevert( + abi.encodeWithSelector( + USDCTokenPool.InvalidDestinationDomain.selector, DEST_DOMAIN_IDENTIFIER, usdcMessage.destinationDomain + ) + ); + + s_usdcTokenPool.validateMessage( + _generateUSDCMessage(usdcMessage), + USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}) + ); + usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER; + + uint32 wrongVersion = usdcMessage.version + 1; + + usdcMessage.version = wrongVersion; + encodedUsdcMessage = _generateUSDCMessage(usdcMessage); + + vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidMessageVersion.selector, wrongVersion)); + s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol new file mode 100644 index 0000000000..bc6108926b --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/USDC/USDCTokenPool/USDCTokenPoolSetup.t.sol @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {USDCTokenPool} from "../../../../pools/USDC/USDCTokenPool.sol"; +import {USDCTokenPoolHelper} from "../../../helpers/USDCTokenPoolHelper.sol"; +import {USDCSetup} from "../USDCSetup.t.sol"; + +contract USDCTokenPoolSetup is USDCSetup { + USDCTokenPoolHelper internal s_usdcTokenPool; + USDCTokenPoolHelper internal s_usdcTokenPoolWithAllowList; + address[] internal s_allowedList; + + function setUp() public virtual override { + super.setUp(); + + s_usdcTokenPool = + new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_allowedList.push(USER_1); + s_usdcTokenPoolWithAllowList = + new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMN), address(s_router)); + + _poolApplyChainUpdates(address(s_usdcTokenPool)); + _poolApplyChainUpdates(address(s_usdcTokenPoolWithAllowList)); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + s_usdcTokenPoolWithAllowList.setDomains(domains); + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol deleted file mode 100644 index da5caba9d7..0000000000 --- a/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol +++ /dev/null @@ -1,702 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; -import {IPoolV1} from "../../interfaces/IPool.sol"; -import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; - -import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {Router} from "../../Router.sol"; -import {Internal} from "../../libraries/Internal.sol"; -import {Pool} from "../../libraries/Pool.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {TokenPool} from "../../pools/TokenPool.sol"; -import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {USDCTokenPoolHelper} from "../helpers/USDCTokenPoolHelper.sol"; -import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; -import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; - -import {IERC165} from "../../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/introspection/IERC165.sol"; - -contract USDCTokenPoolSetup is BaseTest { - IBurnMintERC20 internal s_token; - MockUSDCTokenMessenger internal s_mockUSDC; - MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; - uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; - - struct USDCMessage { - uint32 version; - uint32 sourceDomain; - uint32 destinationDomain; - uint64 nonce; - bytes32 sender; - bytes32 recipient; - bytes32 destinationCaller; - bytes messageBody; - } - - uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; - uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; - - bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); - address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); - address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); - address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); - - address internal s_routerAllowedOnRamp = address(3456); - address internal s_routerAllowedOffRamp = address(234); - Router internal s_router; - - USDCTokenPoolHelper internal s_usdcTokenPool; - USDCTokenPoolHelper internal s_usdcTokenPoolWithAllowList; - address[] internal s_allowedList; - - function setUp() public virtual override { - BaseTest.setUp(); - BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); - s_token = usdcToken; - deal(address(s_token), OWNER, type(uint256).max); - _setUpRamps(); - - s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); - s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); - - usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); - - s_usdcTokenPool = - new USDCTokenPoolHelper(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); - usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); - - s_allowedList.push(USER_1); - s_usdcTokenPoolWithAllowList = - new USDCTokenPoolHelper(s_mockUSDC, s_token, s_allowedList, address(s_mockRMN), address(s_router)); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(address(s_token)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - chainUpdates[1] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), - remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(chainUpdates); - s_usdcTokenPoolWithAllowList.applyChainUpdates(chainUpdates); - - USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); - domains[0] = USDCTokenPool.DomainUpdate({ - destChainSelector: DEST_CHAIN_SELECTOR, - domainIdentifier: 9999, - allowedCaller: keccak256("allowedCaller"), - enabled: true - }); - - s_usdcTokenPool.setDomains(domains); - s_usdcTokenPoolWithAllowList.setDomains(domains); - } - - function _setUpRamps() internal { - s_router = new Router(address(s_token), address(s_mockRMN)); - - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); - Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); - address[] memory offRamps = new address[](1); - offRamps[0] = s_routerAllowedOffRamp; - offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); - - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); - } - - function _generateUSDCMessage( - USDCMessage memory usdcMessage - ) internal pure returns (bytes memory) { - return abi.encodePacked( - usdcMessage.version, - usdcMessage.sourceDomain, - usdcMessage.destinationDomain, - usdcMessage.nonce, - usdcMessage.sender, - usdcMessage.recipient, - usdcMessage.destinationCaller, - usdcMessage.messageBody - ); - } -} - -contract USDCTokenPool_lockOrBurn is USDCTokenPoolSetup { - // Base test case, included for PR gas comparisons as fuzz tests are excluded from forge snapshot due to being flaky. - function test_LockOrBurn_Success() public { - bytes32 receiver = bytes32(uint256(uint160(STRANGER))); - uint256 amount = 1; - s_token.transfer(address(s_usdcTokenPool), amount); - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPool), - receiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(receiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - } - - function test_Fuzz_LockOrBurn_Success(bytes32 destinationReceiver, uint256 amount) public { - vm.assume(destinationReceiver != bytes32(0)); - amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); - s_token.transfer(address(s_usdcTokenPool), amount); - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPool), - destinationReceiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(destinationReceiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); - } - - function test_Fuzz_LockOrBurnWithAllowList_Success(bytes32 destinationReceiver, uint256 amount) public { - vm.assume(destinationReceiver != bytes32(0)); - amount = bound(amount, 1, _getOutboundRateLimiterConfig().capacity); - s_token.transfer(address(s_usdcTokenPoolWithAllowList), amount); - vm.startPrank(s_routerAllowedOnRamp); - - USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPoolWithAllowList.getDomain(DEST_CHAIN_SELECTOR); - - vm.expectEmit(); - emit RateLimiter.TokensConsumed(amount); - vm.expectEmit(); - emit ITokenMessenger.DepositForBurn( - s_mockUSDC.s_nonce(), - address(s_token), - amount, - address(s_usdcTokenPoolWithAllowList), - destinationReceiver, - expectedDomain.domainIdentifier, - s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), - expectedDomain.allowedCaller - ); - vm.expectEmit(); - emit TokenPool.Burned(s_routerAllowedOnRamp, amount); - - Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: s_allowedList[0], - receiver: abi.encodePacked(destinationReceiver), - amount: amount, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); - assertEq(s_mockUSDC.s_nonce() - 1, nonce); - assertEq(poolReturnDataV1.destTokenAddress, abi.encode(DEST_CHAIN_USDC_TOKEN)); - } - - // Reverts - function test_UnknownDomain_Revert() public { - uint64 wrongDomain = DEST_CHAIN_SELECTOR + 1; - // We need to setup the wrong chainSelector so it reaches the domain check - Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); - onRampUpdates[0] = Router.OnRamp({destChainSelector: wrongDomain, onRamp: s_routerAllowedOnRamp}); - s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); - - TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); - chainUpdates[0] = TokenPool.ChainUpdate({ - remoteChainSelector: wrongDomain, - remotePoolAddress: abi.encode(address(1)), - remoteTokenAddress: abi.encode(address(2)), - allowed: true, - outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: _getInboundRateLimiterConfig() - }); - - s_usdcTokenPool.applyChainUpdates(chainUpdates); - - uint256 amount = 1000; - vm.startPrank(s_routerAllowedOnRamp); - deal(address(s_token), s_routerAllowedOnRamp, amount); - s_token.approve(address(s_usdcTokenPool), amount); - - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.UnknownDomain.selector, wrongDomain)); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(address(0)), - amount: amount, - remoteChainSelector: wrongDomain, - localToken: address(s_token) - }) - ); - } - - function test_CallerIsNotARampOnRouter_Revert() public { - vm.expectRevert(abi.encodeWithSelector(TokenPool.CallerIsNotARampOnRouter.selector, OWNER)); - - s_usdcTokenPool.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: OWNER, - receiver: abi.encodePacked(address(0)), - amount: 0, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } - - function test_LockOrBurnWithAllowList_Revert() public { - vm.startPrank(s_routerAllowedOnRamp); - - vm.expectRevert(abi.encodeWithSelector(TokenPool.SenderNotAllowed.selector, STRANGER)); - - s_usdcTokenPoolWithAllowList.lockOrBurn( - Pool.LockOrBurnInV1({ - originalSender: STRANGER, - receiver: abi.encodePacked(address(0)), - amount: 1000, - remoteChainSelector: DEST_CHAIN_SELECTOR, - localToken: address(s_token) - }) - ); - } -} - -contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { - // From https://github.com/circlefin/evm-cctp-contracts/blob/377c9bd813fb86a42d900ae4003599d82aef635a/src/messages/BurnMessage.sol#L57 - function _formatMessage( - uint32 _version, - bytes32 _burnToken, - bytes32 _mintRecipient, - uint256 _amount, - bytes32 _messageSender - ) internal pure returns (bytes memory) { - return abi.encodePacked(_version, _burnToken, _mintRecipient, _amount, _messageSender); - } - - function test_Fuzz_ReleaseOrMint_Success(address recipient, uint256 amount) public { - vm.assume(recipient != address(0) && recipient != address(s_token)); - amount = bound(amount, 0, _getInboundRateLimiterConfig().capacity); - - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: SOURCE_DOMAIN_IDENTIFIER, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: 0x060606060606, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(uint160(recipient))), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: _formatMessage( - 0, - bytes32(uint256(uint160(address(s_token)))), - bytes32(uint256(uint160(recipient))), - amount, - bytes32(uint256(uint160(OWNER))) - ) - }); - - bytes memory message = _generateUSDCMessage(usdcMessage); - bytes memory attestation = bytes("attestation bytes"); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode( - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: message, attestation: attestation})); - - // The mocked receiver does not release the token to the pool, so we manually do it here - deal(address(s_token), address(s_usdcTokenPool), amount); - - vm.expectEmit(); - emit TokenPool.Minted(s_routerAllowedOffRamp, recipient, amount); - - vm.expectCall( - address(s_mockUSDCTransmitter), - abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, message, attestation) - ); - - vm.startPrank(s_routerAllowedOffRamp); - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 - function test_ReleaseOrMintRealTx_Success() public { - bytes memory encodedUsdcMessage = - hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; - bytes memory attestation = bytes("attestation bytes"); - - uint32 nonce = 4730; - uint32 sourceDomain = 3; - uint256 amount = 100; - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - // The mocked receiver does not release the token to the pool, so we manually do it here - deal(address(s_token), address(s_usdcTokenPool), amount); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); - - vm.expectCall( - address(s_mockUSDCTransmitter), - abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) - ); - - vm.startPrank(s_routerAllowedOffRamp); - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - // Reverts - function test_UnlockingUSDCFailed_Revert() public { - vm.startPrank(s_routerAllowedOffRamp); - s_mockUSDCTransmitter.setShouldSucceed(false); - - uint256 amount = 13255235235; - - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: SOURCE_DOMAIN_IDENTIFIER, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: 0x060606060606, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(uint160(address(s_mockUSDC)))), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: _formatMessage( - 0, - bytes32(uint256(uint160(address(s_token)))), - bytes32(uint256(uint160(OWNER))), - amount, - bytes32(uint256(uint160(OWNER))) - ) - }); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode( - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory offchainTokenData = abi.encode( - USDCTokenPool.MessageAndAttestation({message: _generateUSDCMessage(usdcMessage), attestation: bytes("")}) - ); - - vm.expectRevert(USDCTokenPool.UnlockingUSDCFailed.selector); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: OWNER, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } - - function test_TokenMaxCapacityExceeded_Revert() public { - uint256 capacity = _getInboundRateLimiterConfig().capacity; - uint256 amount = 10 * capacity; - address recipient = address(1); - vm.startPrank(s_routerAllowedOffRamp); - - Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ - sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), - destTokenAddress: abi.encode(address(s_usdcTokenPool)), - extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), - destGasAmount: USDC_DEST_TOKEN_GAS - }); - - bytes memory offchainTokenData = - abi.encode(USDCTokenPool.MessageAndAttestation({message: bytes(""), attestation: bytes("")})); - - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.TokenMaxCapacityExceeded.selector, capacity, amount, address(s_token)) - ); - - s_usdcTokenPool.releaseOrMint( - Pool.ReleaseOrMintInV1({ - originalSender: abi.encode(OWNER), - receiver: recipient, - amount: amount, - localToken: address(s_token), - remoteChainSelector: SOURCE_CHAIN_SELECTOR, - sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: sourceTokenData.extraData, - offchainTokenData: offchainTokenData - }) - ); - } -} - -contract USDCTokenPool_supportsInterface is USDCTokenPoolSetup { - function test_SupportsInterface_Success() public view { - assertTrue(s_usdcTokenPool.supportsInterface(type(IPoolV1).interfaceId)); - assertTrue(s_usdcTokenPool.supportsInterface(type(IERC165).interfaceId)); - } -} - -contract USDCTokenPool_setDomains is USDCTokenPoolSetup { - mapping(uint64 destChainSelector => USDCTokenPool.Domain domain) private s_chainToDomain; - - // Setting lower fuzz run as 256 runs was causing differing gas results in snapshot. - /// forge-config: default.fuzz.runs = 32 - /// forge-config: ccip.fuzz.runs = 32 - function test_Fuzz_SetDomains_Success( - bytes32[5] calldata allowedCallers, - uint32[5] calldata domainIdentifiers, - uint64[5] calldata destChainSelectors - ) public { - uint256 numberOfDomains = allowedCallers.length; - USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](numberOfDomains); - for (uint256 i = 0; i < numberOfDomains; ++i) { - vm.assume(allowedCallers[i] != bytes32(0) && domainIdentifiers[i] != 0 && destChainSelectors[i] != 0); - - domainUpdates[i] = USDCTokenPool.DomainUpdate({ - allowedCaller: allowedCallers[i], - domainIdentifier: domainIdentifiers[i], - destChainSelector: destChainSelectors[i], - enabled: true - }); - - s_chainToDomain[destChainSelectors[i]] = - USDCTokenPool.Domain({domainIdentifier: domainIdentifiers[i], allowedCaller: allowedCallers[i], enabled: true}); - } - - vm.expectEmit(); - emit USDCTokenPool.DomainsSet(domainUpdates); - - s_usdcTokenPool.setDomains(domainUpdates); - - for (uint256 i = 0; i < numberOfDomains; ++i) { - USDCTokenPool.Domain memory expected = s_chainToDomain[destChainSelectors[i]]; - USDCTokenPool.Domain memory got = s_usdcTokenPool.getDomain(destChainSelectors[i]); - assertEq(got.allowedCaller, expected.allowedCaller); - assertEq(got.domainIdentifier, expected.domainIdentifier); - } - } - - // Reverts - - function test_OnlyOwner_Revert() public { - USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](0); - - vm.startPrank(STRANGER); - vm.expectRevert("Only callable by owner"); - - s_usdcTokenPool.setDomains(domainUpdates); - } - - function test_InvalidDomain_Revert() public { - bytes32 validCaller = bytes32(uint256(25)); - // Ensure valid domain works - USDCTokenPool.DomainUpdate[] memory domainUpdates = new USDCTokenPool.DomainUpdate[](1); - domainUpdates[0] = USDCTokenPool.DomainUpdate({ - allowedCaller: validCaller, - domainIdentifier: 0, // ensures 0 is valid, as this is eth mainnet - destChainSelector: 45690, - enabled: true - }); - - s_usdcTokenPool.setDomains(domainUpdates); - - // Make update invalid on allowedCaller - domainUpdates[0].allowedCaller = bytes32(0); - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); - - s_usdcTokenPool.setDomains(domainUpdates); - - // Make valid again - domainUpdates[0].allowedCaller = validCaller; - - // Make invalid on destChainSelector - domainUpdates[0].destChainSelector = 0; - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidDomain.selector, domainUpdates[0])); - - s_usdcTokenPool.setDomains(domainUpdates); - } -} - -contract USDCTokenPool__validateMessage is USDCTokenPoolSetup { - function test_Fuzz_ValidateMessage_Success(uint32 sourceDomain, uint64 nonce) public { - vm.pauseGasMetering(); - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: sourceDomain, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: nonce, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(299999)), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: bytes("") - }); - - bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); - - vm.resumeGasMetering(); - s_usdcTokenPool.validateMessage( - encodedUsdcMessage, USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain}) - ); - } - - // Reverts - - function test_ValidateInvalidMessage_Revert() public { - USDCMessage memory usdcMessage = USDCMessage({ - version: 0, - sourceDomain: 1553252, - destinationDomain: DEST_DOMAIN_IDENTIFIER, - nonce: 387289284924, - sender: SOURCE_CHAIN_TOKEN_SENDER, - recipient: bytes32(uint256(92398429395823)), - destinationCaller: bytes32(uint256(uint160(address(s_usdcTokenPool)))), - messageBody: bytes("") - }); - - USDCTokenPool.SourceTokenDataPayload memory sourceTokenData = - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}); - - bytes memory encodedUsdcMessage = _generateUSDCMessage(usdcMessage); - - s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); - - uint32 expectedSourceDomain = usdcMessage.sourceDomain + 1; - - vm.expectRevert( - abi.encodeWithSelector(USDCTokenPool.InvalidSourceDomain.selector, expectedSourceDomain, usdcMessage.sourceDomain) - ); - s_usdcTokenPool.validateMessage( - encodedUsdcMessage, - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: expectedSourceDomain}) - ); - - uint64 expectedNonce = usdcMessage.nonce + 1; - - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidNonce.selector, expectedNonce, usdcMessage.nonce)); - s_usdcTokenPool.validateMessage( - encodedUsdcMessage, - USDCTokenPool.SourceTokenDataPayload({nonce: expectedNonce, sourceDomain: usdcMessage.sourceDomain}) - ); - - usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER + 1; - vm.expectRevert( - abi.encodeWithSelector( - USDCTokenPool.InvalidDestinationDomain.selector, DEST_DOMAIN_IDENTIFIER, usdcMessage.destinationDomain - ) - ); - - s_usdcTokenPool.validateMessage( - _generateUSDCMessage(usdcMessage), - USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: usdcMessage.sourceDomain}) - ); - usdcMessage.destinationDomain = DEST_DOMAIN_IDENTIFIER; - - uint32 wrongVersion = usdcMessage.version + 1; - - usdcMessage.version = wrongVersion; - encodedUsdcMessage = _generateUSDCMessage(usdcMessage); - - vm.expectRevert(abi.encodeWithSelector(USDCTokenPool.InvalidMessageVersion.selector, wrongVersion)); - s_usdcTokenPool.validateMessage(encodedUsdcMessage, sourceTokenData); - } -} diff --git a/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol b/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol index 73c9ba7445..3a97e866a1 100644 --- a/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol +++ b/contracts/src/v0.8/liquiditymanager/test/LiquidityManager.t.sol @@ -57,7 +57,7 @@ contract LiquidityManagerSetup is LiquidityManagerBaseTest { LiquidityManagerBaseTest.setUp(); s_bridgeAdapter = new MockL1BridgeAdapter(s_l1Token, false); - s_lockReleaseTokenPool = new LockReleaseTokenPool(s_l1Token, new address[](0), address(1), true, address(123)); + s_lockReleaseTokenPool = new LockReleaseTokenPool(s_l1Token, 18, new address[](0), address(1), true, address(123)); s_liquidityManager = new LiquidityManagerHelper( s_l1Token, i_localChainSelector, @@ -71,6 +71,7 @@ contract LiquidityManagerSetup is LiquidityManagerBaseTest { s_wethBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l1Weth)), true); s_wethLockReleaseTokenPool = new LockReleaseTokenPool( IERC20(address(s_l1Weth)), + 18, new address[](0), address(1), true, @@ -272,6 +273,7 @@ contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); LockReleaseTokenPool remotePool = new LockReleaseTokenPool( s_l2Token, + 18, new address[](0), address(1), true, @@ -401,6 +403,7 @@ contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(s_l2Token, false); LockReleaseTokenPool remotePool = new LockReleaseTokenPool( s_l2Token, + 18, new address[](0), address(1), true, @@ -522,6 +525,7 @@ contract LiquidityManager_rebalanceLiquidity is LiquidityManagerSetup { MockL1BridgeAdapter remoteBridgeAdapter = new MockL1BridgeAdapter(IERC20(address(s_l2Weth)), true); LockReleaseTokenPool remotePool = new LockReleaseTokenPool( IERC20(address(s_l2Weth)), + 18, new address[](0), address(1), true, @@ -817,6 +821,7 @@ contract LiquidityManager_setLocalLiquidityContainer is LiquidityManagerSetup { function test_setLocalLiquidityContainerSuccess() external { LockReleaseTokenPool newPool = new LockReleaseTokenPool( s_l1Token, + 18, new address[](0), address(1), true, diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.approve.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.approve.t.sol new file mode 100644 index 0000000000..d328eec843 --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.approve.t.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; + +contract BurnMintERC20_approve is BurnMintERC20Setup { + function test_approve() public { + uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); + uint256 sendingAmount = s_amount / 2; + + s_burnMintERC20.approve(STRANGER, sendingAmount); + + uint256 ownerBalancePre = s_burnMintERC20.balanceOf(OWNER); + + changePrank(STRANGER); + + s_burnMintERC20.transferFrom(OWNER, STRANGER, sendingAmount); + + assertEq(sendingAmount + balancePre, s_burnMintERC20.balanceOf(STRANGER)); + assertEq(ownerBalancePre - sendingAmount, s_burnMintERC20.balanceOf(OWNER)); + } + + // Reverts + + function test_approve_RevertWhen_InvalidAddress() public { + vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.InvalidRecipient.selector, address(s_burnMintERC20))); + + s_burnMintERC20.approve(address(s_burnMintERC20), s_amount); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burn.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burn.t.sol new file mode 100644 index 0000000000..75fa6e7337 --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burn.t.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; + +import {IERC20} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; + +contract BurnMintERC20_burn is BurnMintERC20Setup { + function test_BasicBurn() public { + s_burnMintERC20.grantRole(s_burnMintERC20.BURNER_ROLE(), OWNER); + deal(address(s_burnMintERC20), OWNER, s_amount); + + vm.expectEmit(); + emit IERC20.Transfer(OWNER, address(0), s_amount); + + s_burnMintERC20.burn(s_amount); + + assertEq(0, s_burnMintERC20.balanceOf(OWNER)); + } + + // Revert + + function test_burn_RevertWhen_SenderNotBurner() public { + // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful + // and should be checked + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(OWNER), + " is missing role ", + Strings.toHexString(uint256(s_burnMintERC20.BURNER_ROLE()), 32) + ) + ); + + s_burnMintERC20.burnFrom(STRANGER, s_amount); + } + + function test_burn_RevertWhen_ExceedsBalance() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC20.burn(s_amount * 2); + } + + function test_burn_RevertWhen_BurnFromZeroAddress() public { + s_burnMintERC20.grantRole(s_burnMintERC20.BURNER_ROLE(), address(0)); + changePrank(address(0)); + + vm.expectRevert("ERC20: burn from the zero address"); + + s_burnMintERC20.burn(0); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFrom.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFrom.t.sol new file mode 100644 index 0000000000..b32d42a86e --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFrom.t.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; + +import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; + +contract BurnMintERC20_burnFrom is BurnMintERC20Setup { + function setUp() public virtual override { + BurnMintERC20Setup.setUp(); + } + + function test_BurnFrom() public { + s_burnMintERC20.approve(s_mockPool, s_amount); + + changePrank(s_mockPool); + + s_burnMintERC20.burnFrom(OWNER, s_amount); + + assertEq(0, s_burnMintERC20.balanceOf(OWNER)); + } + + // Reverts + + function test_burnFrom_RevertWhen_SenderNotBurner() public { + // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful + // and should be checked + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(OWNER), + " is missing role ", + Strings.toHexString(uint256(s_burnMintERC20.BURNER_ROLE()), 32) + ) + ); + + s_burnMintERC20.burnFrom(OWNER, s_amount); + } + + function test_burnFrom_RevertWhen_InsufficientAllowance() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: insufficient allowance"); + + s_burnMintERC20.burnFrom(OWNER, s_amount); + } + + function test_burnFrom_RevertWhen_ExceedsBalance() public { + s_burnMintERC20.approve(s_mockPool, s_amount * 2); + + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC20.burnFrom(OWNER, s_amount * 2); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFromAlias.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFromAlias.t.sol new file mode 100644 index 0000000000..d619968b8f --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.burnFromAlias.t.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; + +import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; + +contract BurnMintERC20_burnFromAlias is BurnMintERC20Setup { + function setUp() public virtual override { + BurnMintERC20Setup.setUp(); + } + + function test_burn() public { + s_burnMintERC20.approve(s_mockPool, s_amount); + + changePrank(s_mockPool); + + s_burnMintERC20.burn(OWNER, s_amount); + + assertEq(0, s_burnMintERC20.balanceOf(OWNER)); + } + + // Reverts + + function test_burn_RevertWhen_SenderNotBurner() public { + // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful + // and should be checked + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(OWNER), + " is missing role ", + Strings.toHexString(uint256(s_burnMintERC20.BURNER_ROLE()), 32) + ) + ); + + s_burnMintERC20.burn(OWNER, s_amount); + } + + function test_burn_RevertWhen_InsufficientAllowance() public { + changePrank(s_mockPool); + + vm.expectRevert("ERC20: insufficient allowance"); + + s_burnMintERC20.burn(OWNER, s_amount); + } + + function test_burn_RevertWhen_ExceedsBalance() public { + s_burnMintERC20.approve(s_mockPool, s_amount * 2); + + changePrank(s_mockPool); + + vm.expectRevert("ERC20: burn amount exceeds balance"); + + s_burnMintERC20.burn(OWNER, s_amount * 2); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.ccipGetAdmin.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.ccipGetAdmin.t.sol new file mode 100644 index 0000000000..25b9fa8f2d --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.ccipGetAdmin.t.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; + +contract BurnMintERC20_getCCIPAdmin is BurnMintERC20Setup { + function test_getCCIPAdmin() public view { + assertEq(OWNER, s_burnMintERC20.getCCIPAdmin()); + } + + function test_setCCIPAdmin() public { + address newAdmin = makeAddr("newAdmin"); + + vm.expectEmit(); + emit BurnMintERC20.CCIPAdminTransferred(OWNER, newAdmin); + + s_burnMintERC20.setCCIPAdmin(newAdmin); + + assertEq(newAdmin, s_burnMintERC20.getCCIPAdmin()); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.constructor.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.constructor.t.sol new file mode 100644 index 0000000000..b5de63b9b3 --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.constructor.t.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; + +contract BurnMintERC20_constructor is BurnMintERC20Setup { + function test_Constructor() public { + vm.startPrank(s_alice); + + string memory name = "Chainlink token v2"; + string memory symbol = "LINK2"; + uint8 decimals = 19; + uint256 maxSupply = 1e33; + + s_burnMintERC20 = new BurnMintERC20(name, symbol, decimals, maxSupply, 1e18); + + assertEq(name, s_burnMintERC20.name()); + assertEq(symbol, s_burnMintERC20.symbol()); + assertEq(decimals, s_burnMintERC20.decimals()); + assertEq(maxSupply, s_burnMintERC20.maxSupply()); + + assertTrue(s_burnMintERC20.hasRole(s_burnMintERC20.DEFAULT_ADMIN_ROLE(), s_alice)); + assertEq(s_burnMintERC20.balanceOf(s_alice), 1e18); + assertEq(s_burnMintERC20.totalSupply(), 1e18); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.grantMintAndBurnRoles.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.grantMintAndBurnRoles.t.sol new file mode 100644 index 0000000000..7a31d2aa07 --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.grantMintAndBurnRoles.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; + +import {IAccessControl} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol"; + +contract BurnMintERC20_grantMintAndBurnRoles is BurnMintERC20Setup { + function test_GrantMintAndBurnRoles() public { + assertFalse(s_burnMintERC20.hasRole(s_burnMintERC20.MINTER_ROLE(), STRANGER)); + assertFalse(s_burnMintERC20.hasRole(s_burnMintERC20.BURNER_ROLE(), STRANGER)); + + vm.expectEmit(); + emit IAccessControl.RoleGranted(s_burnMintERC20.MINTER_ROLE(), STRANGER, OWNER); + vm.expectEmit(); + emit IAccessControl.RoleGranted(s_burnMintERC20.BURNER_ROLE(), STRANGER, OWNER); + + s_burnMintERC20.grantMintAndBurnRoles(STRANGER); + + assertTrue(s_burnMintERC20.hasRole(s_burnMintERC20.MINTER_ROLE(), STRANGER)); + assertTrue(s_burnMintERC20.hasRole(s_burnMintERC20.BURNER_ROLE(), STRANGER)); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.mint.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.mint.t.sol new file mode 100644 index 0000000000..fd97b80fa6 --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.mint.t.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; + +import {IERC20} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {Strings} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Strings.sol"; + +contract BurnMintERC20_mint is BurnMintERC20Setup { + function test_mint() public { + uint256 balancePre = s_burnMintERC20.balanceOf(OWNER); + + s_burnMintERC20.grantMintAndBurnRoles(OWNER); + + vm.expectEmit(); + emit IERC20.Transfer(address(0), OWNER, s_amount); + + s_burnMintERC20.mint(OWNER, s_amount); + + assertEq(balancePre + s_amount, s_burnMintERC20.balanceOf(OWNER)); + } + + // Revert + + function test_mint_RevertWhen_SenderNotMinter() public { + vm.startPrank(STRANGER); + + // OZ Access Control v4.8.3 inherited by BurnMintERC20 does not use custom errors, but the revert message is still useful + // and should be checked + vm.expectRevert( + abi.encodePacked( + "AccessControl: account ", + Strings.toHexString(STRANGER), + " is missing role ", + Strings.toHexString(uint256(s_burnMintERC20.MINTER_ROLE()), 32) + ) + ); + + s_burnMintERC20.mint(STRANGER, 1e18); + } + + function test_mint_RevertWhen_MaxSupplyExceeded() public { + changePrank(s_mockPool); + + // Mint max supply + s_burnMintERC20.mint(OWNER, s_burnMintERC20.maxSupply()); + + vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.MaxSupplyExceeded.selector, s_burnMintERC20.maxSupply() + 1)); + + // Attempt to mint 1 more than max supply + s_burnMintERC20.mint(OWNER, 1); + } + + function test_mint_RevertWhen_InvalidRecipient() public { + s_burnMintERC20.grantMintAndBurnRoles(OWNER); + + vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.InvalidRecipient.selector, address(s_burnMintERC20))); + s_burnMintERC20.mint(address(s_burnMintERC20), 1e18); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.supportsInterface.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.supportsInterface.t.sol new file mode 100644 index 0000000000..aa495d047e --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.supportsInterface.t.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {IBurnMintERC20} from "../../../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; + +import {IERC20} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "../../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +contract BurnMintERC20_supportsInterface is BurnMintERC20Setup { + function test_SupportsInterface() public view { + assertTrue(s_burnMintERC20.supportsInterface(type(IERC20).interfaceId)); + assertTrue(s_burnMintERC20.supportsInterface(type(IBurnMintERC20).interfaceId)); + assertTrue(s_burnMintERC20.supportsInterface(type(IERC165).interfaceId)); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.transfer.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.transfer.t.sol new file mode 100644 index 0000000000..6d21e50747 --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20.transfer.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20Setup} from "./BurnMintERC20Setup.t.sol"; +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; + +contract BurnMintERC20_transfer is BurnMintERC20Setup { + function test_transfer() public { + uint256 balancePre = s_burnMintERC20.balanceOf(STRANGER); + uint256 sendingAmount = s_amount / 2; + + s_burnMintERC20.transfer(STRANGER, sendingAmount); + + assertEq(sendingAmount + balancePre, s_burnMintERC20.balanceOf(STRANGER)); + } + + // Reverts + + function test_transfer_RevertWhen_InvalidAddress() public { + vm.expectRevert(abi.encodeWithSelector(BurnMintERC20.InvalidRecipient.selector, address(s_burnMintERC20))); + + s_burnMintERC20.transfer(address(s_burnMintERC20), s_amount); + } +} diff --git a/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20Setup.t.sol b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20Setup.t.sol new file mode 100644 index 0000000000..4ba1bd410e --- /dev/null +++ b/contracts/src/v0.8/shared/test/token/ERC20/BurnMintERC20/BurnMintERC20Setup.t.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {BurnMintERC20} from "../../../../token/ERC20/BurnMintERC20.sol"; +import {BaseTest} from "../../../BaseTest.t.sol"; + +contract BurnMintERC20Setup is BaseTest { + BurnMintERC20 internal s_burnMintERC20; + + address internal s_mockPool = makeAddr("s_mockPool"); + uint256 internal s_amount = 1e18; + + address internal s_alice; + + function setUp() public virtual override { + BaseTest.setUp(); + + s_alice = makeAddr("alice"); + + s_burnMintERC20 = new BurnMintERC20("Chainlink Token", "LINK", 18, 1e27, 0); + + // Set s_mockPool to be a burner and minter + s_burnMintERC20.grantMintAndBurnRoles(s_mockPool); + deal(address(s_burnMintERC20), OWNER, s_amount); + } +} diff --git a/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol b/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol new file mode 100644 index 0000000000..946a6623b4 --- /dev/null +++ b/contracts/src/v0.8/shared/token/ERC20/BurnMintERC20.sol @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {IGetCCIPAdmin} from "../../../ccip/interfaces/IGetCCIPAdmin.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {AccessControl} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/AccessControl.sol"; +import {IAccessControl} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/access/IAccessControl.sol"; +import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {ERC20Burnable} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +/// @notice A basic ERC20 compatible token contract with burn and minting roles. +/// @dev The total supply can be limited during deployment. +/// @dev This contract has not been audited and is not yet approved for production use. +contract BurnMintERC20 is IBurnMintERC20, IGetCCIPAdmin, IERC165, ERC20Burnable, AccessControl { + error MaxSupplyExceeded(uint256 supplyAfterMint); + error InvalidRecipient(address recipient); + + event CCIPAdminTransferred(address indexed previousAdmin, address indexed newAdmin); + + /// @dev The number of decimals for the token + uint8 internal immutable i_decimals; + + /// @dev The maximum supply of the token, 0 if unlimited + uint256 internal immutable i_maxSupply; + + /// @dev the CCIPAdmin can be used to register with the CCIP token admin registry, but has no other special powers, + /// and can only be transferred by the owner. + address internal s_ccipAdmin; + + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); + + /// @dev the underscores in parameter names are used to suppress compiler warnings about shadowing ERC20 functions + constructor( + string memory name, + string memory symbol, + uint8 decimals_, + uint256 maxSupply_, + uint256 preMint + ) ERC20(name, symbol) { + i_decimals = decimals_; + i_maxSupply = maxSupply_; + + s_ccipAdmin = msg.sender; + + // Mint the initial supply to the new Owner, saving gas by not calling if the mint amount is zero + if (preMint != 0) _mint(msg.sender, preMint); + + // Set up the owner as the initial minter and burner + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + } + + /// @inheritdoc IERC165 + function supportsInterface(bytes4 interfaceId) public pure virtual override(AccessControl, IERC165) returns (bool) { + return + interfaceId == type(IERC20).interfaceId || + interfaceId == type(IBurnMintERC20).interfaceId || + interfaceId == type(IERC165).interfaceId || + interfaceId == type(IAccessControl).interfaceId || + interfaceId == type(IGetCCIPAdmin).interfaceId; + } + + // ================================================================ + // │ ERC20 │ + // ================================================================ + + /// @dev Returns the number of decimals used in its user representation. + function decimals() public view virtual override returns (uint8) { + return i_decimals; + } + + /// @dev Returns the max supply of the token, 0 if unlimited. + function maxSupply() public view virtual returns (uint256) { + return i_maxSupply; + } + + /// @dev Uses OZ ERC20 _transfer to disallow sending to address(0). + /// @dev Disallows sending to address(this) + function _transfer(address from, address to, uint256 amount) internal virtual override { + if (to == address(this)) revert InvalidRecipient(to); + + super._transfer(from, to, amount); + } + + /// @dev Uses OZ ERC20 _approve to disallow approving for address(0). + /// @dev Disallows approving for address(this) + function _approve(address owner, address spender, uint256 amount) internal virtual override { + if (spender == address(this)) revert InvalidRecipient(spender); + + super._approve(owner, spender, amount); + } + + // ================================================================ + // │ Burning & minting │ + // ================================================================ + + /// @inheritdoc ERC20Burnable + /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). + /// @dev Decreases the total supply. + function burn(uint256 amount) public override(IBurnMintERC20, ERC20Burnable) onlyRole(BURNER_ROLE) { + super.burn(amount); + } + + /// @inheritdoc IBurnMintERC20 + /// @dev Alias for BurnFrom for compatibility with the older naming convention. + /// @dev Uses burnFrom for all validation & logic. + function burn(address account, uint256 amount) public virtual override { + burnFrom(account, amount); + } + + /// @inheritdoc ERC20Burnable + /// @dev Uses OZ ERC20 _burn to disallow burning from address(0). + /// @dev Decreases the total supply. + function burnFrom( + address account, + uint256 amount + ) public override(IBurnMintERC20, ERC20Burnable) onlyRole(BURNER_ROLE) { + super.burnFrom(account, amount); + } + + /// @inheritdoc IBurnMintERC20 + /// @dev Uses OZ ERC20 _mint to disallow minting to address(0). + /// @dev Disallows minting to address(this) + /// @dev Increases the total supply. + function mint(address account, uint256 amount) external override onlyRole(MINTER_ROLE) { + if (account == address(this)) revert InvalidRecipient(account); + if (i_maxSupply != 0 && totalSupply() + amount > i_maxSupply) revert MaxSupplyExceeded(totalSupply() + amount); + + _mint(account, amount); + } + + // ================================================================ + // │ Roles │ + // ================================================================ + + /// @notice grants both mint and burn roles to `burnAndMinter`. + /// @dev calls public functions so this function does not require + /// access controls. This is handled in the inner functions. + function grantMintAndBurnRoles(address burnAndMinter) external { + grantRole(MINTER_ROLE, burnAndMinter); + grantRole(BURNER_ROLE, burnAndMinter); + } + + /// @notice Returns the current CCIPAdmin + function getCCIPAdmin() external view returns (address) { + return s_ccipAdmin; + } + + /// @notice Transfers the CCIPAdmin role to a new address + /// @dev only the owner can call this function, NOT the current ccipAdmin, and 1-step ownership transfer is used. + /// @param newAdmin The address to transfer the CCIPAdmin role to. Setting to address(0) is a valid way to revoke + /// the role + function setCCIPAdmin(address newAdmin) public onlyRole(DEFAULT_ADMIN_ROLE) { + address currentAdmin = s_ccipAdmin; + + s_ccipAdmin = newAdmin; + + emit CCIPAdminTransferred(currentAdmin, newAdmin); + } +} diff --git a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go index 1553ba62b0..def5c4bc25 100644 --- a/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_from_mint_token_pool/burn_from_mint_token_pool.go @@ -74,23 +74,22 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - Allowed bool - RemotePoolAddress []byte + RemotePoolAddresses [][]byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var BurnFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b506040516200450b3803806200450b8339810160408190526200003491620008c0565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c2816200018f565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c05262000168576040805160008152602081019091526200016890846200023a565b5062000185925050506001600160a01b0385163060001962000397565b5050505062000afc565b336001600160a01b03821603620001e95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200025b576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002e65760008382815181106200027f576200027f620009d0565b60209081029190910101519050620002996002826200047d565b15620002dc576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200025e565b5060005b8151811015620003925760008282815181106200030b576200030b620009d0565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000337575062000389565b620003446002826200049d565b1562000387576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002ea565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040f9190620009e6565b6200041b919062000a16565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200047791869190620004b416565b50505050565b600062000494836001600160a01b03841662000585565b90505b92915050565b600062000494836001600160a01b03841662000689565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000503906001600160a01b038516908490620006db565b80519091501562000392578080602001905181019062000524919062000a2c565b620003925760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000086565b600081815260018301602052604081205480156200067e576000620005ac60018362000a57565b8554909150600090620005c29060019062000a57565b90508082146200062e576000866000018281548110620005e657620005e6620009d0565b90600052602060002001549050808760000184815481106200060c576200060c620009d0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000642576200064262000a6d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000497565b600091505062000497565b6000818152600183016020526040812054620006d25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000497565b50600062000497565b6060620006ec8484600085620006f4565b949350505050565b606082471015620007575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000086565b600080866001600160a01b0316858760405162000775919062000aa9565b60006040518083038185875af1925050503d8060008114620007b4576040519150601f19603f3d011682016040523d82523d6000602084013e620007b9565b606091505b509092509050620007cd87838387620007d8565b979650505050505050565b606083156200084c57825160000362000844576001600160a01b0385163b620008445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000086565b5081620006ec565b620006ec8383815115620008635781518083602001fd5b8060405162461bcd60e51b815260040162000086919062000ac7565b6001600160a01b03811681146200089557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008bb816200087f565b919050565b60008060008060808587031215620008d757600080fd5b8451620008e4816200087f565b602086810151919550906001600160401b03808211156200090457600080fd5b818801915088601f8301126200091957600080fd5b8151818111156200092e576200092e62000898565b8060051b604051601f19603f8301168101818110858211171562000956576200095662000898565b60405291825284820192508381018501918b8311156200097557600080fd5b938501935b828510156200099e576200098e85620008ae565b845293850193928501926200097a565b809850505050505050620009b560408601620008ae565b9150620009c560608601620008ae565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009f957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000497576200049762000a00565b60006020828403121562000a3f57600080fd5b8151801515811462000a5057600080fd5b9392505050565b8181038181111562000497576200049762000a00565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aa057818101518382015260200162000a86565b50506000910152565b6000825162000abd81846020870162000a83565b9190910192915050565b602081526000825180602084015262000ae881604085016020870162000a83565b601f01601f19169190910160400192915050565b60805160a05160c05161399262000b79600039600081816104dd01528181611777015261215b0152600081816104b7015281816115a80152611a2d0152600081816102390152818161028e015281816106e0015281816114c80152818161194d01528181611b45015281816120f1015261234601526139926000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc146104a2578063dc0bd971146104b5578063e0351e13146104db578063f2fde38b1461050157600080fd5b8063c4bffe2b14610467578063c75eea9c1461047c578063cf7401f31461048f57600080fd5b8063b0f479a1116100c8578063b0f479a114610423578063b794658014610441578063c0d786551461045457600080fd5b80639a4575b91461037f578063a7cd63b71461039f578063af58d59f146103b457600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103335780637d54534e1461033b5780638926f54f1461034e5780638da5cb5b1461036157600080fd5b806354c8a4f3146102ed5780636d3d1a581461030257806378a010b21461032057600080fd5b806321df0da71161018c57806321df0da714610237578063240028e81461027e57806339077537146102cb57600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612ae9565b610514565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612b48565b6105f9565b6040516101d29190612bc7565b6101ee6040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e30000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c661028c366004612c07565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102de6102d9366004612c24565b6106a9565b604051905181526020016101d2565b6103006102fb366004612cac565b61082f565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610259565b61030061032e366004612d18565b6108aa565b610300610a1e565b610300610349366004612c07565b610b1b565b6101c661035c366004612b48565b610b6a565b60005473ffffffffffffffffffffffffffffffffffffffff16610259565b61039261038d366004612d9b565b610b81565b6040516101d29190612dd6565b6103a7610c28565b6040516101d29190612e36565b6103c76103c2366004612b48565b610c39565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610259565b6101ee61044f366004612b48565b610d0e565b610300610462366004612c07565b610d39565b61046f610e14565b6040516101d29190612e90565b6103c761048a366004612b48565b610ecc565b61030061049d366004612ff8565b610f9e565b6103006104b036600461303d565b611027565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b61030061050f366004612c07565b6114ad565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106249061307f565b80601f01602080910402602001604051908101604052809291908181526020018280546106509061307f565b801561069d5780601f106106725761010080835404028352916020019161069d565b820191906000526020600020905b81548152906001019060200180831161068057829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c96106c48361317d565b6114c1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107156060850160408601612c07565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b506107ae925050506060830160408401612c07565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161081091815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108376116f2565b6108a48484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061177592505050565b50505050565b6108b26116f2565b6108bb83610b6a565b610902576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109299061307f565b80601f01602080910402602001604051908101604052809291908181526020018280546109559061307f565b80156109a25780601f10610977576101008083540402835291602001916109a2565b820191906000526020600020905b81548152906001019060200180831161098557829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109d18385836132c2565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a10939291906133dc565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108f9565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b236116f2565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006105f3600567ffffffffffffffff841661192b565b6040805180820190915260608082526020820152610ba6610ba183613440565b611946565b610bb38260600135611b10565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c0d84602001602081019061044f9190612b48565b81526040805160208181019092526000815291015292915050565b6060610c346002611bb9565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f390611bc6565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106249061307f565b610d416116f2565b73ffffffffffffffffffffffffffffffffffffffff8116610d8e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e226005611bb9565b90506000815167ffffffffffffffff811115610e4057610e40612ed2565b604051908082528060200260200182016040528015610e69578160200160208202803683370190505b50905060005b8251811015610ec557828181518110610e8a57610e8a6134e2565b6020026020010151828281518110610ea457610ea46134e2565b67ffffffffffffffff90921660209283029190910190910152600101610e6f565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f390611bc6565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fde575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611017576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b611022838383611c78565b505050565b61102f6116f2565b60005b8181101561102257600083838381811061104e5761104e6134e2565b90506020028101906110609190613511565b6110699061354f565b905061107e8160800151826020015115611d62565b6110918160a00151826020015115611d62565b80602001511561138d5780516110b39060059067ffffffffffffffff16611e9b565b6110f85780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b604081015151158061110d5750606081015151155b15611144576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906113259082613603565b506060820151600582019061133a9082613603565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c29550611380949392919061371d565b60405180910390a16114a4565b80516113a59060059067ffffffffffffffff16611ea7565b6113ea5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114536004830182612a9b565b611461600583016000612a9b565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611032565b6114b56116f2565b6114be81611eb3565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115565760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611604573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162891906137b6565b1561165f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61166c8160200151611fa8565b600061167b82602001516105f9565b905080516000148061169f575080805190602001208260a001518051906020012014155b156116dc578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f99190612bc7565b6116ee826020015183606001516120ce565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108f9565b565b7f00000000000000000000000000000000000000000000000000000000000000006117cc576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156118625760008382815181106117ec576117ec6134e2565b6020026020010151905061180a81600261211590919063ffffffff16565b156118595760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117cf565b5060005b8151811015611022576000828281518110611883576118836134e2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118c75750611923565b6118d2600282612137565b156119215760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611866565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119db5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906137b6565b15611ae4576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611af18160400151612159565b611afe81602001516121d8565b6114be81602001518260600151612326565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b158015611b9e57600080fd5b505af1158015611bb2573d6000803e3d6000fd5b5050505050565b6060600061193f8361236a565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c5482606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c389190613802565b85608001516fffffffffffffffffffffffffffffffff166123c5565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c8183610b6a565b611cc3576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f9565b611cce826000611d62565b67ffffffffffffffff83166000908152600760205260409020611cf190836123ef565b611cfc816000611d62565b67ffffffffffffffff83166000908152600760205260409020611d2290600201826123ef565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d5593929190613815565b60405180910390a1505050565b815115611e295781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611db8575060408201516fffffffffffffffffffffffffffffffff16155b15611df157816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f99190613898565b80156116ee576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e62575060208201516fffffffffffffffffffffffffffffffff1615155b156116ee57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f99190613898565b600061193f8383612591565b600061193f83836125e0565b3373ffffffffffffffffffffffffffffffffffffffff821603611f32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108f9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fb181610b6a565b611ff3576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612072573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209691906137b6565b6114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90600201827f00000000000000000000000000000000000000000000000000000000000000006126d3565b600061193f8373ffffffffffffffffffffffffffffffffffffffff84166125e0565b600061193f8373ffffffffffffffffffffffffffffffffffffffff8416612591565b7f0000000000000000000000000000000000000000000000000000000000000000156114be5761218a600282612a56565b6114be576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f9565b6121e181610b6a565b612223576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561229c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122c091906138d4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90827f00000000000000000000000000000000000000000000000000000000000000006126d3565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069d57602002820191906000526020600020905b8154815260200190600101908083116123a65750505050509050919050565b60006123e4856123d584866138f1565b6123df9087613908565b612a85565b90505b949350505050565b815460009061241890700100000000000000000000000000000000900463ffffffff1642613802565b905080156124ba5760018301548354612460916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166123c5565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546124e0916fffffffffffffffffffffffffffffffff9081169116612a85565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d55908490613898565b60008181526001830160205260408120546125d8575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f3565b5060006105f3565b600081815260018301602052604081205480156126c9576000612604600183613802565b855490915060009061261890600190613802565b905080821461267d576000866000018281548110612638576126386134e2565b906000526020600020015490508087600001848154811061265b5761265b6134e2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268e5761268e61391b565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f3565b60009150506105f3565b825474010000000000000000000000000000000000000000900460ff1615806126fa575081155b1561270457505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061274a90700100000000000000000000000000000000900463ffffffff1642613802565b9050801561280a578183111561278c576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127c69083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166123c5565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128c15773ffffffffffffffffffffffffffffffffffffffff8416612869576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f9565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f9565b848310156129d45760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906129059082613802565b61290f878a613802565b6129199190613908565b612923919061394a565b905073ffffffffffffffffffffffffffffffffffffffff861661297c576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f9565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f9565b6129de8584613802565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561193f565b6000818310612a94578161193f565b5090919050565b508054612aa79061307f565b6000825580601f10612ab7575050565b601f0160209004906000526020600020908101906114be91905b80821115612ae55760008155600101612ad1565b5090565b600060208284031215612afb57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461193f57600080fd5b803567ffffffffffffffff81168114612b4357600080fd5b919050565b600060208284031215612b5a57600080fd5b61193f82612b2b565b6000815180845260005b81811015612b8957602081850181015186830182015201612b6d565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061193f6020830184612b63565b73ffffffffffffffffffffffffffffffffffffffff811681146114be57600080fd5b8035612b4381612bda565b600060208284031215612c1957600080fd5b813561193f81612bda565b600060208284031215612c3657600080fd5b813567ffffffffffffffff811115612c4d57600080fd5b8201610100818503121561193f57600080fd5b60008083601f840112612c7257600080fd5b50813567ffffffffffffffff811115612c8a57600080fd5b6020830191508360208260051b8501011115612ca557600080fd5b9250929050565b60008060008060408587031215612cc257600080fd5b843567ffffffffffffffff80821115612cda57600080fd5b612ce688838901612c60565b90965094506020870135915080821115612cff57600080fd5b50612d0c87828801612c60565b95989497509550505050565b600080600060408486031215612d2d57600080fd5b612d3684612b2b565b9250602084013567ffffffffffffffff80821115612d5357600080fd5b818601915086601f830112612d6757600080fd5b813581811115612d7657600080fd5b876020828501011115612d8857600080fd5b6020830194508093505050509250925092565b600060208284031215612dad57600080fd5b813567ffffffffffffffff811115612dc457600080fd5b820160a0818503121561193f57600080fd5b602081526000825160406020840152612df26060840182612b63565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e2d8282612b63565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612e52565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8457835167ffffffffffffffff1683529284019291840191600101612eac565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612f2557612f25612ed2565b60405290565b60405160c0810167ffffffffffffffff81118282101715612f2557612f25612ed2565b80151581146114be57600080fd5b8035612b4381612f4e565b80356fffffffffffffffffffffffffffffffff81168114612b4357600080fd5b600060608284031215612f9957600080fd5b6040516060810181811067ffffffffffffffff82111715612fbc57612fbc612ed2565b6040529050808235612fcd81612f4e565b8152612fdb60208401612f67565b6020820152612fec60408401612f67565b60408201525092915050565b600080600060e0848603121561300d57600080fd5b61301684612b2b565b92506130258560208601612f87565b91506130348560808601612f87565b90509250925092565b6000806020838503121561305057600080fd5b823567ffffffffffffffff81111561306757600080fd5b61307385828601612c60565b90969095509350505050565b600181811c9082168061309357607f821691505b6020821081036130cc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126130e357600080fd5b813567ffffffffffffffff808211156130fe576130fe612ed2565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561314457613144612ed2565b8160405283815286602085880101111561315d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561319057600080fd5b613198612f01565b823567ffffffffffffffff808211156131b057600080fd5b6131bc368387016130d2565b83526131ca60208601612b2b565b60208401526131db60408601612bfc565b6040840152606085013560608401526131f660808601612bfc565b608084015260a085013591508082111561320f57600080fd5b61321b368387016130d2565b60a084015260c085013591508082111561323457600080fd5b613240368387016130d2565b60c084015260e085013591508082111561325957600080fd5b50613266368286016130d2565b60e08301525092915050565b601f821115611022576000816000526020600020601f850160051c8101602086101561329b5750805b601f850160051c820191505b818110156132ba578281556001016132a7565b505050505050565b67ffffffffffffffff8311156132da576132da612ed2565b6132ee836132e8835461307f565b83613272565b6000601f841160018114613340576000851561330a5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611bb2565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561338f578685013582556020948501946001909201910161336f565b50868210156133ca577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006133ef6040830186612b63565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561345257600080fd5b60405160a0810167ffffffffffffffff828210818311171561347657613476612ed2565b81604052843591508082111561348b57600080fd5b50613498368286016130d2565b8252506134a760208401612b2b565b602082015260408301356134ba81612bda565b60408201526060838101359082015260808301356134d781612bda565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261354557600080fd5b9190910192915050565b6000610140823603121561356257600080fd5b61356a612f2b565b61357383612b2b565b815261358160208401612f5c565b6020820152604083013567ffffffffffffffff808211156135a157600080fd5b6135ad368387016130d2565b604084015260608501359150808211156135c657600080fd5b506135d3368286016130d2565b6060830152506135e63660808501612f87565b60808201526135f83660e08501612f87565b60a082015292915050565b815167ffffffffffffffff81111561361d5761361d612ed2565b6136318161362b845461307f565b84613272565b602080601f831160018114613684576000841561364e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556132ba565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156136d1578886015182559484019460019091019084016136b2565b508582101561370d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261374181840187612b63565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061377f9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e2d565b6000602082840312156137c857600080fd5b815161193f81612f4e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f3576105f36137d3565b67ffffffffffffffff8416815260e0810161386160208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526123e7565b606081016105f382848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156138e657600080fd5b815161193f81612bda565b80820281158282048414176105f3576105f36137d3565b808201808211156105f3576105f36137d3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082613980577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004c6338038062004c63833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161402e62000c356000396000818161054f01528181611d8201526127d30152600081816105290152818161189f015261206e0152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b6901528181611bce01528181611c270152611cc90152600081816102470152818161029c01528181610708015281816121f10152818161276901526129be015261402e6000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e236600461317e565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601b81526020017f4275726e46726f6d4d696e74546f6b656e506f6f6c20312e352e31000000000081525081565b6040516101f39190613224565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a366004613259565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d610318366004613276565b61067e565b604051905181526020016101f3565b6101e761033a3660046132cf565b61084d565b61035261034d36600461339e565b610897565b005b6103526103623660046132cf565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b366004613259565b610a7d565b6101e76103ae36600461340a565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df366004613425565b610b15565b6040516101f39190613460565b6104046103ff36600461340a565b610bee565b6040516101f391906134b7565b610419610d59565b6040516101f39190613539565b6103526104343660046132cf565b610d6a565b61044c61044736600461340a565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d436600461340a565b610f57565b6103526104e7366004613259565b611007565b6104f46110e2565b6040516101f39190613593565b61044c61050f36600461340a565b61119a565b61035261052236600461371b565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b61035261058136600461339e565b6112f0565b610352610594366004613259565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c0870187613760565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d6060860160408701613259565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d3925050506060840160408501613259565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f83836040516108629291906137c5565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d12565b949350505050565b61089f611d2d565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d8092505050565b50505050565b61091a611d2d565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3692505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611d2d565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611d12565b6040805180820190915260608082526020820152610b3282612030565b610b3f82606001356121bc565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d4919061340a565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c179060050161225e565b90506000815167ffffffffffffffff811115610c3557610c356135d5565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6137d5565b602002602001015181526020019081526020016000208054610cae90613804565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda90613804565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6137d5565b6020908102919091010152600101610c6e565b509392505050565b6060610d65600261225e565b905090565b610d72611d2d565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd09291906137c5565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061226b565b610e39578282826040517f74f23c7c000000000000000000000000000000000000000000000000000000008152600401610961939291906138a0565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e759291906138c4565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067890612277565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f8290613804565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae90613804565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611d2d565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f0600561225e565b90506000815167ffffffffffffffff81111561110e5761110e6135d5565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586137d5565b6020026020010151828281518110611172576111726137d5565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067890612277565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa838383612329565b6112f8611d2d565b60005b838110156114e5576000858583818110611317576113176137d5565b905060200201602081019061132c919061340a565b9050611343600567ffffffffffffffff831661226b565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa9060050161225e565b905060005b81518110156114165761140d8282815181106113cd576113cd6137d5565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226b90919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f6004830182613111565b6005820160008181611491828261314b565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056137d5565b905060200281019061151791906138d8565b611520906139a4565b905061153181606001516000612413565b61154081608001516000612413565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff16612550565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f9082613b1b565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6137d5565b6020026020010151611f36565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613c35565b60405180910390a150506001016114e9565b5050505050565b61180a611d2d565b6118138161255c565b50565b61182961029a60a0830160808401613259565b6118885761183d60a0820160808301613259565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d4604084016020850161340a565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613cce565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b3604083016020840161340a565b612620565b6119d86119cb604083016020840161340a565b61033a60a0840184613760565b611a1d576119e960a0820182613760565b6040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109619291906138c4565b611813611a30604083016020840161340a565b8260600135612746565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109619190613224565b600082806020019051810190611abf9190613ceb565b905060ff81111561067857826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016109619190613224565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c1f576000611b8e7f000000000000000000000000000000000000000000000000000000000000000084613d33565b9050604d8160ff161115611c02576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611c0d81600a613e6c565b611c179085613e7b565b915050610678565b6000611c4b837f0000000000000000000000000000000000000000000000000000000000000000613d33565b9050604d8160ff161180611c925750611c6581600a613e6c565b611c8f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e7b565b84115b15611cfd576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611d0881600a613e6c565b61088f9085613eb6565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d7e576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd7576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e6d576000838281518110611df757611df76137d5565b60200260200101519050611e1581600261278d90919063ffffffff16565b15611e645760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dda565b5060005b81518110156109aa576000828281518110611e8e57611e8e6137d5565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ed25750611f2e565b611edd6002826127af565b15611f2c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e71565b8051600003611f71576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611fa39060050182612550565b611fdd5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613ecd565b6000818152600860205260409020611ff58382613b1b565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e759190613224565b61204361029a60a0830160808401613259565b6120575761183d60a0820160808301613259565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6120a3604084016020850161340a565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121389190613cce565b1561216f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121876121826060830160408401613259565b6127d1565b61219f61219a604083016020840161340a565b612850565b6118136121b2604083016020840161340a565b826060013561299e565b6040517f79cc6790000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906379cc679090604401600060405180830381600087803b15801561224a57600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611d26836129e2565b6000611d268383612a3d565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261230582606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e99190613ef0565b85608001516fffffffffffffffffffffffffffffffff16612b30565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61233283610afe565b612374576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b61237f826000612413565b67ffffffffffffffff831660009081526007602052604090206123a29083612b58565b6123ad816000612413565b67ffffffffffffffff831660009081526007602052604090206123d39060020182612b58565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161240693929190613f03565b60405180910390a1505050565b8151156124de5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612469575060408201516fffffffffffffffffffffffffffffffff16155b156124a257816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613f86565b80156124da576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612517575060208201516fffffffffffffffffffffffffffffffff1615155b156124da57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613f86565b6000611d268383612cfa565b3373ffffffffffffffffffffffffffffffffffffffff8216036125ab576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262981610afe565b61266b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061270e9190613cce565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124da90600201827f0000000000000000000000000000000000000000000000000000000000000000612d49565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612a3d565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612cfa565b7f000000000000000000000000000000000000000000000000000000000000000015611813576128026002826130cc565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61285981610afe565b61289b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612914573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129389190613fc2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124da90827f0000000000000000000000000000000000000000000000000000000000000000612d49565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b815481526020019060010190808311612a1e5750505050509050919050565b60008181526001830160205260408120548015612b26576000612a61600183613ef0565b8554909150600090612a7590600190613ef0565b9050808214612ada576000866000018281548110612a9557612a956137d5565b9060005260206000200154905080876000018481548110612ab857612ab86137d5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612aeb57612aeb613fdf565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612b4f85612b408486613eb6565b612b4a908761400e565b6130fb565b95945050505050565b8154600090612b8190700100000000000000000000000000000000900463ffffffff1642613ef0565b90508015612c235760018301548354612bc9916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b30565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c49916fffffffffffffffffffffffffffffffff90811691166130fb565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612406908490613f86565b6000818152600183016020526040812054612d4157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612d70575081155b15612d7a57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612dc090700100000000000000000000000000000000900463ffffffff1642613ef0565b90508015612e805781831115612e02576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e3c9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b30565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f375773ffffffffffffffffffffffffffffffffffffffff8416612edf576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b8483101561304a5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f7b9082613ef0565b612f85878a613ef0565b612f8f919061400e565b612f999190613e7b565b905073ffffffffffffffffffffffffffffffffffffffff8616612ff2576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b6130548584613ef0565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d26565b600081831061310a5781611d26565b5090919050565b50805461311d90613804565b6000825580601f1061312d575050565b601f0160209004906000526020600020908101906118139190613165565b508054600082559060005260206000209081019061181391905b5b8082111561317a5760008155600101613166565b5090565b60006020828403121561319057600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d2657600080fd5b6000815180845260005b818110156131e6576020818501810151868301820152016131ca565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d2660208301846131c0565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561326b57600080fd5b8135611d2681613237565b60006020828403121561328857600080fd5b813567ffffffffffffffff81111561329f57600080fd5b82016101008185031215611d2657600080fd5b803567ffffffffffffffff811681146132ca57600080fd5b919050565b6000806000604084860312156132e457600080fd5b6132ed846132b2565b9250602084013567ffffffffffffffff8082111561330a57600080fd5b818601915086601f83011261331e57600080fd5b81358181111561332d57600080fd5b87602082850101111561333f57600080fd5b6020830194508093505050509250925092565b60008083601f84011261336457600080fd5b50813567ffffffffffffffff81111561337c57600080fd5b6020830191508360208260051b850101111561339757600080fd5b9250929050565b600080600080604085870312156133b457600080fd5b843567ffffffffffffffff808211156133cc57600080fd5b6133d888838901613352565b909650945060208701359150808211156133f157600080fd5b506133fe87828801613352565b95989497509550505050565b60006020828403121561341c57600080fd5b611d26826132b2565b60006020828403121561343757600080fd5b813567ffffffffffffffff81111561344e57600080fd5b820160a08185031215611d2657600080fd5b60208152600082516040602084015261347c60608401826131c0565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4f82826131c0565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561352c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261351a8583516131c0565b945092850192908501906001016134e0565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613555565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358757835167ffffffffffffffff16835292840192918401916001016135af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613627576136276135d5565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613674576136746135d5565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff811681146132ca57600080fd5b6000606082840312156136bc57600080fd5b6040516060810181811067ffffffffffffffff821117156136df576136df6135d5565b60405290508082356136f08161367c565b81526136fe6020840161368a565b602082015261370f6040840161368a565b60408201525092915050565b600080600060e0848603121561373057600080fd5b613739846132b2565b925061374885602086016136aa565b915061375785608086016136aa565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261379557600080fd5b83018035915067ffffffffffffffff8211156137b057600080fd5b60200191503681900382131561339757600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381857607f821691505b602082108103613851577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b4f604083018486613857565b60208152600061088f602083018486613857565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390c57600080fd5b9190910192915050565b600082601f83011261392757600080fd5b813567ffffffffffffffff811115613941576139416135d5565b61397260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161362d565b81815284602083860101111561398757600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b757600080fd5b6139bf613604565b6139c8836132b2565b815260208084013567ffffffffffffffff808211156139e657600080fd5b9085019036601f8301126139f957600080fd5b813581811115613a0b57613a0b6135d5565b8060051b613a1a85820161362d565b9182528381018501918581019036841115613a3457600080fd5b86860192505b83831015613a7057823585811115613a525760008081fd5b613a603689838a0101613916565b8352509186019190860190613a3a565b8087890152505050506040860135925080831115613a8d57600080fd5b5050613a9b36828601613916565b604083015250613aae36606085016136aa565b6060820152613ac03660c085016136aa565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c81016020861015613af45750805b601f850160051c820191505b81811015613b1357828155600101613b00565b505050505050565b815167ffffffffffffffff811115613b3557613b356135d5565b613b4981613b438454613804565b84613acb565b602080601f831160018114613b9c5760008415613b665750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b13565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be957888601518255948401946001909101908401613bca565b5085821015613c2557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c59818401876131c0565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c979050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b4f565b600060208284031215613ce057600080fd5b8151611d268161367c565b600060208284031215613cfd57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613d04565b600181815b80851115613da557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8b57613d8b613d04565b80851615613d9857918102915b93841c9390800290613d51565b509250929050565b600082613dbc57506001610678565b81613dc957506000610678565b8160018114613ddf5760028114613de957613e05565b6001915050610678565b60ff841115613dfa57613dfa613d04565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613e28575081810a610678565b613e328383613d4c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e6457613e64613d04565b029392505050565b6000611d2660ff841683613dad565b600082613eb1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613d04565b67ffffffffffffffff8316815260406020820152600061088f60408301846131c0565b8181038181111561067857610678613d04565b67ffffffffffffffff8416815260e08101613f4f60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fd457600080fd5b8151611d2681613237565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613d0456fea164736f6c6343000818000a", } var BurnFromMintTokenPoolABI = BurnFromMintTokenPoolMetaData.ABI var BurnFromMintTokenPoolBin = BurnFromMintTokenPoolMetaData.Bin -func DeployBurnFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnFromMintTokenPool, error) { +func DeployBurnFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnFromMintTokenPool, error) { parsed, err := BurnFromMintTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -99,7 +98,7 @@ func DeployBurnFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractB return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnFromMintTokenPoolBin), backend, token, allowlist, rmnProxy, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnFromMintTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router) if err != nil { return common.Address{}, nil, nil, err } @@ -332,26 +331,26 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetRateLimitAd return _BurnFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnFromMintTokenPool.CallOpts) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { var out []interface{} - err := _BurnFromMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + err := _BurnFromMintTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) if err != nil { - return *new([]byte), err + return *new([][]byte), err } - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) return out0, err } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _BurnFromMintTokenPool.Contract.GetRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _BurnFromMintTokenPool.Contract.GetRemotePools(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _BurnFromMintTokenPool.Contract.GetRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _BurnFromMintTokenPool.Contract.GetRemotePools(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector) } func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -464,6 +463,50 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetToken() (co return _BurnFromMintTokenPool.Contract.GetToken(&_BurnFromMintTokenPool.CallOpts) } +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _BurnFromMintTokenPool.contract.Call(opts, &out, "getTokenDecimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) GetTokenDecimals() (uint8, error) { + return _BurnFromMintTokenPool.Contract.GetTokenDecimals(&_BurnFromMintTokenPool.CallOpts) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { + return _BurnFromMintTokenPool.Contract.GetTokenDecimals(&_BurnFromMintTokenPool.CallOpts) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + var out []interface{} + err := _BurnFromMintTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _BurnFromMintTokenPool.Contract.IsRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _BurnFromMintTokenPool.Contract.IsRemotePool(&_BurnFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnFromMintTokenPool *BurnFromMintTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _BurnFromMintTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -586,6 +629,18 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) AcceptOwne return _BurnFromMintTokenPool.Contract.AcceptOwnership(&_BurnFromMintTokenPool.TransactOpts) } +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.AddRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.AddRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -598,16 +653,16 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ApplyAllow return _BurnFromMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnFromMintTokenPool.TransactOpts, removes, adds) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", chains) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, chains) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, chains) +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -634,6 +689,18 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) ReleaseOrM return _BurnFromMintTokenPool.Contract.ReleaseOrMint(&_BurnFromMintTokenPool.TransactOpts, releaseOrMintIn) } +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.RemoveRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnFromMintTokenPool.Contract.RemoveRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -658,18 +725,6 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetRateLim return _BurnFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnFromMintTokenPool.TransactOpts, rateLimitAdmin) } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.SetRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnFromMintTokenPool.Contract.SetRemotePool(&_BurnFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnFromMintTokenPool *BurnFromMintTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _BurnFromMintTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2066,6 +2121,123 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseOwnershipTrans return event, nil } +type BurnFromMintTokenPoolRateLimitAdminSetIterator struct { + Event *BurnFromMintTokenPoolRateLimitAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnFromMintTokenPoolRateLimitAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnFromMintTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BurnFromMintTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BurnFromMintTokenPoolRateLimitAdminSetIterator) Error() error { + return it.fail +} + +func (it *BurnFromMintTokenPoolRateLimitAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnFromMintTokenPoolRateLimitAdminSet struct { + RateLimitAdmin common.Address + Raw types.Log +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnFromMintTokenPoolRateLimitAdminSetIterator, error) { + + logs, sub, err := _BurnFromMintTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return &BurnFromMintTokenPoolRateLimitAdminSetIterator{contract: _BurnFromMintTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRateLimitAdminSet) (event.Subscription, error) { + + logs, sub, err := _BurnFromMintTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnFromMintTokenPoolRateLimitAdminSet) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*BurnFromMintTokenPoolRateLimitAdminSet, error) { + event := new(BurnFromMintTokenPoolRateLimitAdminSet) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type BurnFromMintTokenPoolReleasedIterator struct { Event *BurnFromMintTokenPoolReleased @@ -2203,8 +2375,136 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseReleased(log t return event, nil } -type BurnFromMintTokenPoolRemotePoolSetIterator struct { - Event *BurnFromMintTokenPoolRemotePoolSet +type BurnFromMintTokenPoolRemotePoolAddedIterator struct { + Event *BurnFromMintTokenPoolRemotePoolAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnFromMintTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BurnFromMintTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Error() error { + return it.fail +} + +func (it *BurnFromMintTokenPoolRemotePoolAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnFromMintTokenPoolRemotePoolAdded struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolAddedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &BurnFromMintTokenPoolRemotePoolAddedIterator{contract: _BurnFromMintTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnFromMintTokenPoolRemotePoolAdded) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*BurnFromMintTokenPoolRemotePoolAdded, error) { + event := new(BurnFromMintTokenPoolRemotePoolAdded) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnFromMintTokenPoolRemotePoolRemovedIterator struct { + Event *BurnFromMintTokenPoolRemotePoolRemoved contract *bind.BoundContract event string @@ -2215,7 +2515,7 @@ type BurnFromMintTokenPoolRemotePoolSetIterator struct { fail error } -func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Next() bool { +func (it *BurnFromMintTokenPoolRemotePoolRemovedIterator) Next() bool { if it.fail != nil { return false @@ -2224,7 +2524,7 @@ func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BurnFromMintTokenPoolRemotePoolSet) + it.Event = new(BurnFromMintTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2239,7 +2539,7 @@ func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(BurnFromMintTokenPoolRemotePoolSet) + it.Event = new(BurnFromMintTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2254,44 +2554,43 @@ func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Next() bool { } } -func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Error() error { +func (it *BurnFromMintTokenPoolRemotePoolRemovedIterator) Error() error { return it.fail } -func (it *BurnFromMintTokenPoolRemotePoolSetIterator) Close() error { +func (it *BurnFromMintTokenPoolRemotePoolRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type BurnFromMintTokenPoolRemotePoolSet struct { +type BurnFromMintTokenPoolRemotePoolRemoved struct { RemoteChainSelector uint64 - PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolSetIterator, error) { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolRemovedIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _BurnFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } - return &BurnFromMintTokenPoolRemotePoolSetIterator{contract: _BurnFromMintTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil + return &BurnFromMintTokenPoolRemotePoolRemovedIterator{contract: _BurnFromMintTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _BurnFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2301,8 +2600,8 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolSet( select { case log := <-logs: - event := new(BurnFromMintTokenPoolRemotePoolSet) - if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + event := new(BurnFromMintTokenPoolRemotePoolRemoved) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return err } event.Raw = log @@ -2323,9 +2622,9 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) WatchRemotePoolSet( }), nil } -func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*BurnFromMintTokenPoolRemotePoolSet, error) { - event := new(BurnFromMintTokenPoolRemotePoolSet) - if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { +func (_BurnFromMintTokenPool *BurnFromMintTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*BurnFromMintTokenPoolRemotePoolRemoved, error) { + event := new(BurnFromMintTokenPoolRemotePoolRemoved) + if err := _BurnFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return nil, err } event.Raw = log @@ -2591,10 +2890,14 @@ func (_BurnFromMintTokenPool *BurnFromMintTokenPool) ParseLog(log types.Log) (ge return _BurnFromMintTokenPool.ParseOwnershipTransferRequested(log) case _BurnFromMintTokenPool.abi.Events["OwnershipTransferred"].ID: return _BurnFromMintTokenPool.ParseOwnershipTransferred(log) + case _BurnFromMintTokenPool.abi.Events["RateLimitAdminSet"].ID: + return _BurnFromMintTokenPool.ParseRateLimitAdminSet(log) case _BurnFromMintTokenPool.abi.Events["Released"].ID: return _BurnFromMintTokenPool.ParseReleased(log) - case _BurnFromMintTokenPool.abi.Events["RemotePoolSet"].ID: - return _BurnFromMintTokenPool.ParseRemotePoolSet(log) + case _BurnFromMintTokenPool.abi.Events["RemotePoolAdded"].ID: + return _BurnFromMintTokenPool.ParseRemotePoolAdded(log) + case _BurnFromMintTokenPool.abi.Events["RemotePoolRemoved"].ID: + return _BurnFromMintTokenPool.ParseRemotePoolRemoved(log) case _BurnFromMintTokenPool.abi.Events["RouterUpdated"].ID: return _BurnFromMintTokenPool.ParseRouterUpdated(log) case _BurnFromMintTokenPool.abi.Events["TokensConsumed"].ID: @@ -2649,12 +2952,20 @@ func (BurnFromMintTokenPoolOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (BurnFromMintTokenPoolRateLimitAdminSet) Topic() common.Hash { + return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174") +} + func (BurnFromMintTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (BurnFromMintTokenPoolRemotePoolSet) Topic() common.Hash { - return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +func (BurnFromMintTokenPoolRemotePoolAdded) Topic() common.Hash { + return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") +} + +func (BurnFromMintTokenPoolRemotePoolRemoved) Topic() common.Hash { + return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") } func (BurnFromMintTokenPoolRouterUpdated) Topic() common.Hash { @@ -2680,7 +2991,7 @@ type BurnFromMintTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) + GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2692,6 +3003,10 @@ type BurnFromMintTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) + GetTokenDecimals(opts *bind.CallOpts) (uint8, error) + + IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) + IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -2704,20 +3019,22 @@ type BurnFromMintTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) - SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -2788,17 +3105,29 @@ type BurnFromMintTokenPoolInterface interface { ParseOwnershipTransferred(log types.Log) (*BurnFromMintTokenPoolOwnershipTransferred, error) + FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnFromMintTokenPoolRateLimitAdminSetIterator, error) + + WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRateLimitAdminSet) (event.Subscription, error) + + ParseRateLimitAdminSet(log types.Log) (*BurnFromMintTokenPoolRateLimitAdminSet, error) + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnFromMintTokenPoolReleasedIterator, error) WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) ParseReleased(log types.Log) (*BurnFromMintTokenPoolReleased, error) - FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolSetIterator, error) + FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolAddedIterator, error) + + WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolAdded(log types.Log) (*BurnFromMintTokenPoolRemotePoolAdded, error) + + FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnFromMintTokenPoolRemotePoolRemovedIterator, error) - WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolSet(log types.Log) (*BurnFromMintTokenPoolRemotePoolSet, error) + ParseRemotePoolRemoved(log types.Log) (*BurnFromMintTokenPoolRemotePoolRemoved, error) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnFromMintTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go index 244f04596a..ecfad493c2 100644 --- a/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_mint_token_pool/burn_mint_token_pool.go @@ -74,23 +74,22 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - Allowed bool - RemotePoolAddress []byte + RemotePoolAddresses [][]byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var BurnMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620040b3380380620040b383398101604081905262000034916200054c565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c28162000176565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c052620001685760408051600081526020810190915262000168908462000221565b5050505050505050620006aa565b336001600160a01b03821603620001d05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c05162000242576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002cd5760008382815181106200026657620002666200065c565b60209081029190910101519050620002806002826200037e565b15620002c3576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000245565b5060005b815181101562000379576000828281518110620002f257620002f26200065c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200031e575062000370565b6200032b6002826200039e565b156200036e576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d1565b505050565b600062000395836001600160a01b038416620003b5565b90505b92915050565b600062000395836001600160a01b038416620004b9565b60008181526001830160205260408120548015620004ae576000620003dc60018362000672565b8554909150600090620003f29060019062000672565b90508082146200045e5760008660000182815481106200041657620004166200065c565b90600052602060002001549050808760000184815481106200043c576200043c6200065c565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000472576200047262000694565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000398565b600091505062000398565b6000818152600183016020526040812054620005025750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000398565b50600062000398565b6001600160a01b03811681146200052157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000547816200050b565b919050565b600080600080608085870312156200056357600080fd5b845162000570816200050b565b602086810151919550906001600160401b03808211156200059057600080fd5b818801915088601f830112620005a557600080fd5b815181811115620005ba57620005ba62000524565b8060051b604051601f19603f83011681018181108582111715620005e257620005e262000524565b60405291825284820192508381018501918b8311156200060157600080fd5b938501935b828510156200062a576200061a856200053a565b8452938501939285019262000606565b80985050505050505062000641604086016200053a565b915062000651606086016200053a565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b818103818111156200039857634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05161398c62000727600039600081816104dd0152818161177701526121550152600081816104b7015281816115a80152611a2d0152600081816102390152818161028e015281816106e0015281816114c80152818161194d01528181611b3f015281816120eb0152612340015261398c6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc146104a2578063dc0bd971146104b5578063e0351e13146104db578063f2fde38b1461050157600080fd5b8063c4bffe2b14610467578063c75eea9c1461047c578063cf7401f31461048f57600080fd5b8063b0f479a1116100c8578063b0f479a114610423578063b794658014610441578063c0d786551461045457600080fd5b80639a4575b91461037f578063a7cd63b71461039f578063af58d59f146103b457600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103335780637d54534e1461033b5780638926f54f1461034e5780638da5cb5b1461036157600080fd5b806354c8a4f3146102ed5780636d3d1a581461030257806378a010b21461032057600080fd5b806321df0da71161018c57806321df0da714610237578063240028e81461027e57806339077537146102cb57600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612ae3565b610514565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612b42565b6105f9565b6040516101d29190612bc1565b6101ee6040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3000000000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c661028c366004612c01565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102de6102d9366004612c1e565b6106a9565b604051905181526020016101d2565b6103006102fb366004612ca6565b61082f565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610259565b61030061032e366004612d12565b6108aa565b610300610a1e565b610300610349366004612c01565b610b1b565b6101c661035c366004612b42565b610b6a565b60005473ffffffffffffffffffffffffffffffffffffffff16610259565b61039261038d366004612d95565b610b81565b6040516101d29190612dd0565b6103a7610c28565b6040516101d29190612e30565b6103c76103c2366004612b42565b610c39565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610259565b6101ee61044f366004612b42565b610d0e565b610300610462366004612c01565b610d39565b61046f610e14565b6040516101d29190612e8a565b6103c761048a366004612b42565b610ecc565b61030061049d366004612ff2565b610f9e565b6103006104b0366004613037565b611027565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b61030061050f366004612c01565b6114ad565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061062490613079565b80601f016020809104026020016040519081016040528092919081815260200182805461065090613079565b801561069d5780601f106106725761010080835404028352916020019161069d565b820191906000526020600020905b81548152906001019060200180831161068057829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c96106c483613177565b6114c1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107156060850160408601612c01565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078557600080fd5b505af1158015610799573d6000803e3d6000fd5b506107ae925050506060830160408401612c01565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161081091815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108376116f2565b6108a48484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061177592505050565b50505050565b6108b26116f2565b6108bb83610b6a565b610902576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff83166000908152600760205260408120600401805461092990613079565b80601f016020809104026020016040519081016040528092919081815260200182805461095590613079565b80156109a25780601f10610977576101008083540402835291602001916109a2565b820191906000526020600020905b81548152906001019060200180831161098557829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109d18385836132bc565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a10939291906133d6565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108f9565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b236116f2565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006105f3600567ffffffffffffffff841661192b565b6040805180820190915260608082526020820152610ba6610ba18361343a565b611946565b610bb38260600135611b10565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c0d84602001602081019061044f9190612b42565b81526040805160208181019092526000815291015292915050565b6060610c346002611bb3565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f390611bc0565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061062490613079565b610d416116f2565b73ffffffffffffffffffffffffffffffffffffffff8116610d8e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e226005611bb3565b90506000815167ffffffffffffffff811115610e4057610e40612ecc565b604051908082528060200260200182016040528015610e69578160200160208202803683370190505b50905060005b8251811015610ec557828181518110610e8a57610e8a6134dc565b6020026020010151828281518110610ea457610ea46134dc565b67ffffffffffffffff90921660209283029190910190910152600101610e6f565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f390611bc0565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fde575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611017576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b611022838383611c72565b505050565b61102f6116f2565b60005b8181101561102257600083838381811061104e5761104e6134dc565b9050602002810190611060919061350b565b61106990613549565b905061107e8160800151826020015115611d5c565b6110918160a00151826020015115611d5c565b80602001511561138d5780516110b39060059067ffffffffffffffff16611e95565b6110f85780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b604081015151158061110d5750606081015151155b15611144576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c1790911696151502959095179098559081015194015193811693169091029190911760038201559151909190600482019061132590826135fd565b506060820151600582019061133a90826135fd565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506113809493929190613717565b60405180910390a16114a4565b80516113a59060059067ffffffffffffffff16611ea1565b6113ea5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f9565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114536004830182612a95565b611461600583016000612a95565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b50600101611032565b6114b56116f2565b6114be81611ead565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115565760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611604573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162891906137b0565b1561165f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61166c8160200151611fa2565b600061167b82602001516105f9565b905080516000148061169f575080805190602001208260a001518051906020012014155b156116dc578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f99190612bc1565b6116ee826020015183606001516120c8565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108f9565b565b7f00000000000000000000000000000000000000000000000000000000000000006117cc576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82518110156118625760008382815181106117ec576117ec6134dc565b6020026020010151905061180a81600261210f90919063ffffffff16565b156118595760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117cf565b5060005b8151811015611022576000828281518110611883576118836134dc565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118c75750611923565b6118d2600282612131565b156119215760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611866565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119db5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f9565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aad91906137b0565b15611ae4576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611af18160400151612153565b611afe81602001516121d2565b6114be81602001518260600151612320565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b158015611b9857600080fd5b505af1158015611bac573d6000803e3d6000fd5b5050505050565b6060600061193f83612364565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c4e82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c3291906137fc565b85608001516fffffffffffffffffffffffffffffffff166123bf565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c7b83610b6a565b611cbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f9565b611cc8826000611d5c565b67ffffffffffffffff83166000908152600760205260409020611ceb90836123e9565b611cf6816000611d5c565b67ffffffffffffffff83166000908152600760205260409020611d1c90600201826123e9565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d4f9392919061380f565b60405180910390a1505050565b815115611e235781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611db2575060408201516fffffffffffffffffffffffffffffffff16155b15611deb57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f99190613892565b80156116ee576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e5c575060208201516fffffffffffffffffffffffffffffffff1615155b156116ee57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f99190613892565b600061193f838361258b565b600061193f83836125da565b3373ffffffffffffffffffffffffffffffffffffffff821603611f2c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108f9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fab81610b6a565b611fed576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561206c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209091906137b0565b6114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90600201827f00000000000000000000000000000000000000000000000000000000000000006126cd565b600061193f8373ffffffffffffffffffffffffffffffffffffffff84166125da565b600061193f8373ffffffffffffffffffffffffffffffffffffffff841661258b565b7f0000000000000000000000000000000000000000000000000000000000000000156114be57612184600282612a50565b6114be576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f9565b6121db81610b6a565b61221d576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f9565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ba91906138ce565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114be576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f9565b67ffffffffffffffff821660009081526007602052604090206116ee90827f00000000000000000000000000000000000000000000000000000000000000006126cd565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069d57602002820191906000526020600020905b8154815260200190600101908083116123a05750505050509050919050565b60006123de856123cf84866138eb565b6123d99087613902565b612a7f565b90505b949350505050565b815460009061241290700100000000000000000000000000000000900463ffffffff16426137fc565b905080156124b4576001830154835461245a916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166123bf565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546124da916fffffffffffffffffffffffffffffffff9081169116612a7f565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d4f908490613892565b60008181526001830160205260408120546125d2575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f3565b5060006105f3565b600081815260018301602052604081205480156126c35760006125fe6001836137fc565b8554909150600090612612906001906137fc565b9050808214612677576000866000018281548110612632576126326134dc565b9060005260206000200154905080876000018481548110612655576126556134dc565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268857612688613915565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f3565b60009150506105f3565b825474010000000000000000000000000000000000000000900460ff1615806126f4575081155b156126fe57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061274490700100000000000000000000000000000000900463ffffffff16426137fc565b905080156128045781831115612786576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127c09083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166123bf565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128bb5773ffffffffffffffffffffffffffffffffffffffff8416612863576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f9565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f9565b848310156129ce5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906128ff90826137fc565b612909878a6137fc565b6129139190613902565b61291d9190613944565b905073ffffffffffffffffffffffffffffffffffffffff8616612976576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f9565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f9565b6129d885846137fc565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561193f565b6000818310612a8e578161193f565b5090919050565b508054612aa190613079565b6000825580601f10612ab1575050565b601f0160209004906000526020600020908101906114be91905b80821115612adf5760008155600101612acb565b5090565b600060208284031215612af557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461193f57600080fd5b803567ffffffffffffffff81168114612b3d57600080fd5b919050565b600060208284031215612b5457600080fd5b61193f82612b25565b6000815180845260005b81811015612b8357602081850181015186830182015201612b67565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061193f6020830184612b5d565b73ffffffffffffffffffffffffffffffffffffffff811681146114be57600080fd5b8035612b3d81612bd4565b600060208284031215612c1357600080fd5b813561193f81612bd4565b600060208284031215612c3057600080fd5b813567ffffffffffffffff811115612c4757600080fd5b8201610100818503121561193f57600080fd5b60008083601f840112612c6c57600080fd5b50813567ffffffffffffffff811115612c8457600080fd5b6020830191508360208260051b8501011115612c9f57600080fd5b9250929050565b60008060008060408587031215612cbc57600080fd5b843567ffffffffffffffff80821115612cd457600080fd5b612ce088838901612c5a565b90965094506020870135915080821115612cf957600080fd5b50612d0687828801612c5a565b95989497509550505050565b600080600060408486031215612d2757600080fd5b612d3084612b25565b9250602084013567ffffffffffffffff80821115612d4d57600080fd5b818601915086601f830112612d6157600080fd5b813581811115612d7057600080fd5b876020828501011115612d8257600080fd5b6020830194508093505050509250925092565b600060208284031215612da757600080fd5b813567ffffffffffffffff811115612dbe57600080fd5b820160a0818503121561193f57600080fd5b602081526000825160406020840152612dec6060840182612b5d565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e278282612b5d565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e7e57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612e4c565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e7e57835167ffffffffffffffff1683529284019291840191600101612ea6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612f1f57612f1f612ecc565b60405290565b60405160c0810167ffffffffffffffff81118282101715612f1f57612f1f612ecc565b80151581146114be57600080fd5b8035612b3d81612f48565b80356fffffffffffffffffffffffffffffffff81168114612b3d57600080fd5b600060608284031215612f9357600080fd5b6040516060810181811067ffffffffffffffff82111715612fb657612fb6612ecc565b6040529050808235612fc781612f48565b8152612fd560208401612f61565b6020820152612fe660408401612f61565b60408201525092915050565b600080600060e0848603121561300757600080fd5b61301084612b25565b925061301f8560208601612f81565b915061302e8560808601612f81565b90509250925092565b6000806020838503121561304a57600080fd5b823567ffffffffffffffff81111561306157600080fd5b61306d85828601612c5a565b90969095509350505050565b600181811c9082168061308d57607f821691505b6020821081036130c6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126130dd57600080fd5b813567ffffffffffffffff808211156130f8576130f8612ecc565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561313e5761313e612ecc565b8160405283815286602085880101111561315757600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561318a57600080fd5b613192612efb565b823567ffffffffffffffff808211156131aa57600080fd5b6131b6368387016130cc565b83526131c460208601612b25565b60208401526131d560408601612bf6565b6040840152606085013560608401526131f060808601612bf6565b608084015260a085013591508082111561320957600080fd5b613215368387016130cc565b60a084015260c085013591508082111561322e57600080fd5b61323a368387016130cc565b60c084015260e085013591508082111561325357600080fd5b50613260368286016130cc565b60e08301525092915050565b601f821115611022576000816000526020600020601f850160051c810160208610156132955750805b601f850160051c820191505b818110156132b4578281556001016132a1565b505050505050565b67ffffffffffffffff8311156132d4576132d4612ecc565b6132e8836132e28354613079565b8361326c565b6000601f84116001811461333a57600085156133045750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611bac565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156133895786850135825560209485019460019092019101613369565b50868210156133c4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006133e96040830186612b5d565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561344c57600080fd5b60405160a0810167ffffffffffffffff828210818311171561347057613470612ecc565b81604052843591508082111561348557600080fd5b50613492368286016130cc565b8252506134a160208401612b25565b602082015260408301356134b481612bd4565b60408201526060838101359082015260808301356134d181612bd4565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261353f57600080fd5b9190910192915050565b6000610140823603121561355c57600080fd5b613564612f25565b61356d83612b25565b815261357b60208401612f56565b6020820152604083013567ffffffffffffffff8082111561359b57600080fd5b6135a7368387016130cc565b604084015260608501359150808211156135c057600080fd5b506135cd368286016130cc565b6060830152506135e03660808501612f81565b60808201526135f23660e08501612f81565b60a082015292915050565b815167ffffffffffffffff81111561361757613617612ecc565b61362b816136258454613079565b8461326c565b602080601f83116001811461367e57600084156136485750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556132b4565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156136cb578886015182559484019460019091019084016136ac565b508582101561370757878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261373b81840187612b5d565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506137799050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e27565b6000602082840312156137c257600080fd5b815161193f81612f48565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f3576105f36137cd565b67ffffffffffffffff8416815260e0810161385b60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526123e1565b606081016105f382848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156138e057600080fd5b815161193f81612bd4565b80820281158282048414176105f3576105f36137cd565b808201808211156105f3576105f36137cd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261397a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004809380380620048098339810160408190526200003591620005a2565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001eb565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006c4565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db908462000265565b5050505050505050505062000730565b336001600160a01b038216036200021557604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e05162000286576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000311576000838281518110620002aa57620002aa620006e2565b60209081029190910101519050620002c4600282620003c2565b1562000307576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000289565b5060005b8151811015620003bd576000828281518110620003365762000336620006e2565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003625750620003b4565b6200036f600282620003e2565b15620003b2576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000315565b505050565b6000620003d9836001600160a01b038416620003f9565b90505b92915050565b6000620003d9836001600160a01b038416620004fd565b60008181526001830160205260408120548015620004f257600062000420600183620006f8565b85549091506000906200043690600190620006f8565b9050808214620004a25760008660000182815481106200045a576200045a620006e2565b9060005260206000200154905080876000018481548110620004805762000480620006e2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004b657620004b66200071a565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003dc565b6000915050620003dc565b60008181526001830160205260408120546200054657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003dc565b506000620003dc565b6001600160a01b03811681146200056557600080fd5b50565b805160ff811681146200057a57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b80516200057a816200054f565b600080600080600060a08688031215620005bb57600080fd5b8551620005c8816200054f565b94506020620005d987820162000568565b60408801519095506001600160401b0380821115620005f757600080fd5b818901915089601f8301126200060c57600080fd5b8151818111156200062157620006216200057f565b8060051b604051601f19603f830116810181811085821117156200064957620006496200057f565b60405291825284820192508381018501918c8311156200066857600080fd5b938501935b828510156200069157620006818562000595565b845293850193928501926200066d565b809850505050505050620006a86060870162000595565b9150620006b86080870162000595565b90509295509295909350565b600060208284031215620006d757600080fd5b620003d98262000568565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003dc57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051614028620007e16000396000818161054f01528181611d8201526127cd0152600081816105290152818161189f015261206e0152600081816102e001528181610ba901528181611a4801528181611b0201528181611b3601528181611b6901528181611bce01528181611c270152611cc90152600081816102470152818161029c01528181610708015281816121eb0152818161276301526129b801526140286000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610527578063e0351e131461054d578063e8a1da1714610573578063f2fde38b1461058657600080fd5b8063c0d78655146104d9578063c4bffe2b146104ec578063c75eea9c14610501578063cf7401f31461051457600080fd5b8063acfecf91116100de578063acfecf9114610426578063af58d59f14610439578063b0f479a1146104a8578063b7946580146104c657600080fd5b80639a4575b9146103d1578063a42a7b8b146103f1578063a7cd63b71461041157600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba5097146103855780637d54534e1461038d5780638926f54f146103a05780638da5cb5b146103b357600080fd5b806354c8a4f31461033f57806362ddd3c4146103545780636d3d1a581461036757600080fd5b8063240028e8116101ad578063240028e81461028c57806324f65ee7146102d9578063390775371461030a5780634c5ef0ed1461032c57600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da714610245575b600080fd5b6101e76101e2366004613178565b610599565b60405190151581526020015b60405180910390f35b6102386040518060400160405280601781526020017f4275726e4d696e74546f6b656e506f6f6c20312e352e3100000000000000000081525081565b6040516101f3919061321e565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e761029a366004613253565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031d610318366004613270565b61067e565b604051905181526020016101f3565b6101e761033a3660046132c9565b61084d565b61035261034d366004613398565b610897565b005b6103526103623660046132c9565b610912565b60095473ffffffffffffffffffffffffffffffffffffffff16610267565b6103526109af565b61035261039b366004613253565b610a7d565b6101e76103ae366004613404565b610afe565b60015473ffffffffffffffffffffffffffffffffffffffff16610267565b6103e46103df36600461341f565b610b15565b6040516101f3919061345a565b6104046103ff366004613404565b610bee565b6040516101f391906134b1565b610419610d59565b6040516101f39190613533565b6103526104343660046132c9565b610d6a565b61044c610447366004613404565b610e82565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610267565b6102386104d4366004613404565b610f57565b6103526104e7366004613253565b611007565b6104f46110e2565b6040516101f3919061358d565b61044c61050f366004613404565b61119a565b610352610522366004613715565b61126c565b7f0000000000000000000000000000000000000000000000000000000000000000610267565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b610352610581366004613398565b6112f0565b610352610594366004613253565b611802565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067857507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261069682611816565b60006106ef60608401356106ea6106b060c087018761375a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3a92505050565b611afe565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f1961073d6060860160408701613253565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107aa57600080fd5b505af11580156107be573d6000803e3d6000fd5b506107d3925050506060840160408501613253565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161083191815260200190565b60405180910390a3604080516020810190915290815292915050565b600061088f83836040516108629291906137bf565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d12565b949350505050565b61089f611d2d565b61090c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d8092505050565b50505050565b61091a611d2d565b61092383610afe565b61096a576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109aa8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3692505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a00576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a85611d2d565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610678600567ffffffffffffffff8416611d12565b6040805180820190915260608082526020820152610b3282612030565b610b3f82606001356121bc565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b998460200160208101906104d49190613404565b8152602001610be66040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1790600501612258565b90506000815167ffffffffffffffff811115610c3557610c356135cf565b604051908082528060200260200182016040528015610c6857816020015b6060815260200190600190039081610c535790505b50905060005b8251811015610d515760086000848381518110610c8d57610c8d6137cf565b602002602001015181526020019081526020016000208054610cae906137fe565b80601f0160208091040260200160405190810160405280929190818152602001828054610cda906137fe565b8015610d275780601f10610cfc57610100808354040283529160200191610d27565b820191906000526020600020905b815481529060010190602001808311610d0a57829003601f168201915b5050505050828281518110610d3e57610d3e6137cf565b6020908102919091010152600101610c6e565b509392505050565b6060610d656002612258565b905090565b610d72611d2d565b610d7b83610afe565b610dbd576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b610dfd8282604051610dd09291906137bf565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612265565b610e39578282826040517f74f23c7c0000000000000000000000000000000000000000000000000000000081526004016109619392919061389a565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e759291906138be565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067890612271565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f82906137fe565b80601f0160208091040260200160405190810160405280929190818152602001828054610fae906137fe565b8015610ffb5780601f10610fd057610100808354040283529160200191610ffb565b820191906000526020600020905b815481529060010190602001808311610fde57829003601f168201915b50505050509050919050565b61100f611d2d565b73ffffffffffffffffffffffffffffffffffffffff811661105c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110f06005612258565b90506000815167ffffffffffffffff81111561110e5761110e6135cf565b604051908082528060200260200182016040528015611137578160200160208202803683370190505b50905060005b825181101561119357828181518110611158576111586137cf565b6020026020010151828281518110611172576111726137cf565b67ffffffffffffffff9092166020928302919091019091015260010161113d565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067890612271565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112ac575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112e5576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b6109aa838383612323565b6112f8611d2d565b60005b838110156114e5576000858583818110611317576113176137cf565b905060200201602081019061132c9190613404565b9050611343600567ffffffffffffffff8316612265565b611385576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b67ffffffffffffffff811660009081526007602052604081206113aa90600501612258565b905060005b81518110156114165761140d8282815181106113cd576113cd6137cf565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226590919063ffffffff16565b506001016113af565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff0000000000000000000000000000000000000000009081168255600182018390556002820180549091169055600381018290559061147f600483018261310b565b60058201600081816114918282613145565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114d3915050565b60405180910390a150506001016112fb565b5060005b818110156117fb576000838383818110611505576115056137cf565b905060200281019061151791906138d2565b6115209061399e565b90506115318160600151600061240d565b6115408160800151600061240d565b80604001515160000361157f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115979060059067ffffffffffffffff1661254a565b6115dc5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610961565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a90910299909316171790941695909517909255909202909117600382015590820151600482019061175f9082613b15565b5060005b8260200151518110156117a35761179b83600001518460200151838151811061178e5761178e6137cf565b6020026020010151611f36565b600101611763565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e99493929190613c2f565b60405180910390a150506001016114e9565b5050505050565b61180a611d2d565b61181381612556565b50565b61182961029a60a0830160808401613253565b6118885761183d60a0820160808301613253565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610961565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118d46040840160208501613404565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190613cc8565b156119a0576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b86119b36040830160208401613404565b61261a565b6119d86119cb6040830160208401613404565b61033a60a084018461375a565b611a1d576119e960a082018261375a565b6040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016109619291906138be565b611813611a306040830160208401613404565b8260600135612740565b60008151600003611a6c57507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa957816040517f953576f7000000000000000000000000000000000000000000000000000000008152600401610961919061321e565b600082806020019051810190611abf9190613ce5565b905060ff81111561067857826040517f953576f7000000000000000000000000000000000000000000000000000000008152600401610961919061321e565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b34575081610678565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c1f576000611b8e7f000000000000000000000000000000000000000000000000000000000000000084613d2d565b9050604d8160ff161115611c02576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611c0d81600a613e66565b611c179085613e75565b915050610678565b6000611c4b837f0000000000000000000000000000000000000000000000000000000000000000613d2d565b9050604d8160ff161180611c925750611c6581600a613e66565b611c8f907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e75565b84115b15611cfd576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610961565b611d0881600a613e66565b61088f9085613eb0565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d7e576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd7576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e6d576000838281518110611df757611df76137cf565b60200260200101519050611e1581600261278790919063ffffffff16565b15611e645760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dda565b5060005b81518110156109aa576000828281518110611e8e57611e8e6137cf565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ed25750611f2e565b611edd6002826127a9565b15611f2c5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e71565b8051600003611f71576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611fa3906005018261254a565b611fdd5782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610961929190613ec7565b6000818152600860205260409020611ff58382613b15565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e75919061321e565b61204361029a60a0830160808401613253565b6120575761183d60a0820160808301613253565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6120a36040840160208501613404565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121389190613cc8565b1561216f576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6121876121826060830160408401613253565b6127cb565b61219f61219a6040830160208401613404565b61284a565b6118136121b26040830160208401613404565b8260600135612998565b6040517f42966c68000000000000000000000000000000000000000000000000000000008152600481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906342966c6890602401600060405180830381600087803b15801561224457600080fd5b505af11580156117fb573d6000803e3d6000fd5b60606000611d26836129dc565b6000611d268383612a37565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526122ff82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e39190613eea565b85608001516fffffffffffffffffffffffffffffffff16612b2a565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61232c83610afe565b61236e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610961565b61237982600061240d565b67ffffffffffffffff8316600090815260076020526040902061239c9083612b52565b6123a781600061240d565b67ffffffffffffffff831660009081526007602052604090206123cd9060020182612b52565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161240093929190613efd565b60405180910390a1505050565b8151156124d85781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612463575060408201516fffffffffffffffffffffffffffffffff16155b1561249c57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016109619190613f80565b80156124d4576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612511575060208201516fffffffffffffffffffffffffffffffff1615155b156124d457816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016109619190613f80565b6000611d268383612cf4565b3373ffffffffffffffffffffffffffffffffffffffff8216036125a5576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262381610afe565b612665576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127089190613cc8565b611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124d490600201827f0000000000000000000000000000000000000000000000000000000000000000612d43565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612a37565b6000611d268373ffffffffffffffffffffffffffffffffffffffff8416612cf4565b7f000000000000000000000000000000000000000000000000000000000000000015611813576127fc6002826130c6565b611813576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610961565b61285381610afe565b612895576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610961565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561290e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129329190613fbc565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611813576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610961565b67ffffffffffffffff821660009081526007602052604090206124d490827f0000000000000000000000000000000000000000000000000000000000000000612d43565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b815481526020019060010190808311612a185750505050509050919050565b60008181526001830160205260408120548015612b20576000612a5b600183613eea565b8554909150600090612a6f90600190613eea565b9050808214612ad4576000866000018281548110612a8f57612a8f6137cf565b9060005260206000200154905080876000018481548110612ab257612ab26137cf565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ae557612ae5613fd9565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610678565b6000915050610678565b6000612b4985612b3a8486613eb0565b612b449087614008565b6130f5565b95945050505050565b8154600090612b7b90700100000000000000000000000000000000900463ffffffff1642613eea565b90508015612c1d5760018301548354612bc3916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b2a565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c43916fffffffffffffffffffffffffffffffff90811691166130f5565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612400908490613f80565b6000818152600183016020526040812054612d3b57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610678565b506000610678565b825474010000000000000000000000000000000000000000900460ff161580612d6a575081155b15612d7457505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612dba90700100000000000000000000000000000000900463ffffffff1642613eea565b90508015612e7a5781831115612dfc576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e369083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b2a565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f315773ffffffffffffffffffffffffffffffffffffffff8416612ed9576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610961565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610961565b848310156130445760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f759082613eea565b612f7f878a613eea565b612f899190614008565b612f939190613e75565b905073ffffffffffffffffffffffffffffffffffffffff8616612fec576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610961565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610961565b61304e8584613eea565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d26565b60008183106131045781611d26565b5090919050565b508054613117906137fe565b6000825580601f10613127575050565b601f016020900490600052602060002090810190611813919061315f565b508054600082559060005260206000209081019061181391905b5b808211156131745760008155600101613160565b5090565b60006020828403121561318a57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d2657600080fd5b6000815180845260005b818110156131e0576020818501810151868301820152016131c4565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d2660208301846131ba565b73ffffffffffffffffffffffffffffffffffffffff8116811461181357600080fd5b60006020828403121561326557600080fd5b8135611d2681613231565b60006020828403121561328257600080fd5b813567ffffffffffffffff81111561329957600080fd5b82016101008185031215611d2657600080fd5b803567ffffffffffffffff811681146132c457600080fd5b919050565b6000806000604084860312156132de57600080fd5b6132e7846132ac565b9250602084013567ffffffffffffffff8082111561330457600080fd5b818601915086601f83011261331857600080fd5b81358181111561332757600080fd5b87602082850101111561333957600080fd5b6020830194508093505050509250925092565b60008083601f84011261335e57600080fd5b50813567ffffffffffffffff81111561337657600080fd5b6020830191508360208260051b850101111561339157600080fd5b9250929050565b600080600080604085870312156133ae57600080fd5b843567ffffffffffffffff808211156133c657600080fd5b6133d28883890161334c565b909650945060208701359150808211156133eb57600080fd5b506133f88782880161334c565b95989497509550505050565b60006020828403121561341657600080fd5b611d26826132ac565b60006020828403121561343157600080fd5b813567ffffffffffffffff81111561344857600080fd5b820160a08185031215611d2657600080fd5b60208152600082516040602084015261347660608401826131ba565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4982826131ba565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613526577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526135148583516131ba565b945092850192908501906001016134da565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161354f565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358157835167ffffffffffffffff16835292840192918401916001016135a9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613621576136216135cf565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561366e5761366e6135cf565b604052919050565b801515811461181357600080fd5b80356fffffffffffffffffffffffffffffffff811681146132c457600080fd5b6000606082840312156136b657600080fd5b6040516060810181811067ffffffffffffffff821117156136d9576136d96135cf565b60405290508082356136ea81613676565b81526136f860208401613684565b602082015261370960408401613684565b60408201525092915050565b600080600060e0848603121561372a57600080fd5b613733846132ac565b925061374285602086016136a4565b915061375185608086016136a4565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261378f57600080fd5b83018035915067ffffffffffffffff8211156137aa57600080fd5b60200191503681900382131561339157600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381257607f821691505b60208210810361384b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b49604083018486613851565b60208152600061088f602083018486613851565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390657600080fd5b9190910192915050565b600082601f83011261392157600080fd5b813567ffffffffffffffff81111561393b5761393b6135cf565b61396c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613627565b81815284602083860101111561398157600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b157600080fd5b6139b96135fe565b6139c2836132ac565b815260208084013567ffffffffffffffff808211156139e057600080fd5b9085019036601f8301126139f357600080fd5b813581811115613a0557613a056135cf565b8060051b613a14858201613627565b9182528381018501918581019036841115613a2e57600080fd5b86860192505b83831015613a6a57823585811115613a4c5760008081fd5b613a5a3689838a0101613910565b8352509186019190860190613a34565b8087890152505050506040860135925080831115613a8757600080fd5b5050613a9536828601613910565b604083015250613aa836606085016136a4565b6060820152613aba3660c085016136a4565b608082015292915050565b601f8211156109aa576000816000526020600020601f850160051c81016020861015613aee5750805b601f850160051c820191505b81811015613b0d57828155600101613afa565b505050505050565b815167ffffffffffffffff811115613b2f57613b2f6135cf565b613b4381613b3d84546137fe565b84613ac5565b602080601f831160018114613b965760008415613b605750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b0d565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be357888601518255948401946001909101908401613bc4565b5085821015613c1f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c53818401876131ba565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c919050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b49565b600060208284031215613cda57600080fd5b8151611d2681613676565b600060208284031215613cf757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067857610678613cfe565b600181815b80851115613d9f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8557613d85613cfe565b80851615613d9257918102915b93841c9390800290613d4b565b509250929050565b600082613db657506001610678565b81613dc357506000610678565b8160018114613dd95760028114613de357613dff565b6001915050610678565b60ff841115613df457613df4613cfe565b50506001821b610678565b5060208310610133831016604e8410600b8410161715613e22575081810a610678565b613e2c8383613d46565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e5e57613e5e613cfe565b029392505050565b6000611d2660ff841683613da7565b600082613eab577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067857610678613cfe565b67ffffffffffffffff8316815260406020820152600061088f60408301846131ba565b8181038181111561067857610678613cfe565b67ffffffffffffffff8416815260e08101613f4960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c083015261088f565b6060810161067882848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fce57600080fd5b8151611d2681613231565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067857610678613cfe56fea164736f6c6343000818000a", } var BurnMintTokenPoolABI = BurnMintTokenPoolMetaData.ABI var BurnMintTokenPoolBin = BurnMintTokenPoolMetaData.Bin -func DeployBurnMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnMintTokenPool, error) { +func DeployBurnMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnMintTokenPool, error) { parsed, err := BurnMintTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -99,7 +98,7 @@ func DeployBurnMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBacke return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnMintTokenPoolBin), backend, token, allowlist, rmnProxy, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnMintTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router) if err != nil { return common.Address{}, nil, nil, err } @@ -332,26 +331,26 @@ func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetRateLimitAdmin() (c return _BurnMintTokenPool.Contract.GetRateLimitAdmin(&_BurnMintTokenPool.CallOpts) } -func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { +func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { var out []interface{} - err := _BurnMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + err := _BurnMintTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) if err != nil { - return *new([]byte), err + return *new([][]byte), err } - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) return out0, err } -func (_BurnMintTokenPool *BurnMintTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _BurnMintTokenPool.Contract.GetRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnMintTokenPool *BurnMintTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _BurnMintTokenPool.Contract.GetRemotePools(&_BurnMintTokenPool.CallOpts, remoteChainSelector) } -func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _BurnMintTokenPool.Contract.GetRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _BurnMintTokenPool.Contract.GetRemotePools(&_BurnMintTokenPool.CallOpts, remoteChainSelector) } func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -464,6 +463,50 @@ func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetToken() (common.Add return _BurnMintTokenPool.Contract.GetToken(&_BurnMintTokenPool.CallOpts) } +func (_BurnMintTokenPool *BurnMintTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _BurnMintTokenPool.contract.Call(opts, &out, "getTokenDecimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_BurnMintTokenPool *BurnMintTokenPoolSession) GetTokenDecimals() (uint8, error) { + return _BurnMintTokenPool.Contract.GetTokenDecimals(&_BurnMintTokenPool.CallOpts) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { + return _BurnMintTokenPool.Contract.GetTokenDecimals(&_BurnMintTokenPool.CallOpts) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + var out []interface{} + err := _BurnMintTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BurnMintTokenPool *BurnMintTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _BurnMintTokenPool.Contract.IsRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _BurnMintTokenPool.Contract.IsRemotePool(&_BurnMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnMintTokenPool *BurnMintTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _BurnMintTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -586,6 +629,18 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) AcceptOwnership() return _BurnMintTokenPool.Contract.AcceptOwnership(&_BurnMintTokenPool.TransactOpts) } +func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.AddRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.AddRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -598,16 +653,16 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ApplyAllowListUpda return _BurnMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnMintTokenPool.TransactOpts, removes, adds) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnMintTokenPool.contract.Transact(opts, "applyChainUpdates", chains) +func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnMintTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) } -func (_BurnMintTokenPool *BurnMintTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, chains) +func (_BurnMintTokenPool *BurnMintTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, chains) +func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.ApplyChainUpdates(&_BurnMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -634,6 +689,18 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) ReleaseOrMint(rele return _BurnMintTokenPool.Contract.ReleaseOrMint(&_BurnMintTokenPool.TransactOpts, releaseOrMintIn) } +func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.RemoveRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnMintTokenPool.Contract.RemoveRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -658,18 +725,6 @@ func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetRateLimitAdmin( return _BurnMintTokenPool.Contract.SetRateLimitAdmin(&_BurnMintTokenPool.TransactOpts, rateLimitAdmin) } -func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.SetRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnMintTokenPool *BurnMintTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnMintTokenPool.Contract.SetRemotePool(&_BurnMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnMintTokenPool *BurnMintTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _BurnMintTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2066,6 +2121,123 @@ func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseOwnershipTransferred(l return event, nil } +type BurnMintTokenPoolRateLimitAdminSetIterator struct { + Event *BurnMintTokenPoolRateLimitAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnMintTokenPoolRateLimitAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnMintTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BurnMintTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BurnMintTokenPoolRateLimitAdminSetIterator) Error() error { + return it.fail +} + +func (it *BurnMintTokenPoolRateLimitAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnMintTokenPoolRateLimitAdminSet struct { + RateLimitAdmin common.Address + Raw types.Log +} + +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnMintTokenPoolRateLimitAdminSetIterator, error) { + + logs, sub, err := _BurnMintTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return &BurnMintTokenPoolRateLimitAdminSetIterator{contract: _BurnMintTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil +} + +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRateLimitAdminSet) (event.Subscription, error) { + + logs, sub, err := _BurnMintTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnMintTokenPoolRateLimitAdminSet) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*BurnMintTokenPoolRateLimitAdminSet, error) { + event := new(BurnMintTokenPoolRateLimitAdminSet) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type BurnMintTokenPoolReleasedIterator struct { Event *BurnMintTokenPoolReleased @@ -2203,8 +2375,136 @@ func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseReleased(log types.Log return event, nil } -type BurnMintTokenPoolRemotePoolSetIterator struct { - Event *BurnMintTokenPoolRemotePoolSet +type BurnMintTokenPoolRemotePoolAddedIterator struct { + Event *BurnMintTokenPoolRemotePoolAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnMintTokenPoolRemotePoolAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnMintTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BurnMintTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BurnMintTokenPoolRemotePoolAddedIterator) Error() error { + return it.fail +} + +func (it *BurnMintTokenPoolRemotePoolAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnMintTokenPoolRemotePoolAdded struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolAddedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnMintTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &BurnMintTokenPoolRemotePoolAddedIterator{contract: _BurnMintTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil +} + +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnMintTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnMintTokenPoolRemotePoolAdded) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*BurnMintTokenPoolRemotePoolAdded, error) { + event := new(BurnMintTokenPoolRemotePoolAdded) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnMintTokenPoolRemotePoolRemovedIterator struct { + Event *BurnMintTokenPoolRemotePoolRemoved contract *bind.BoundContract event string @@ -2215,7 +2515,7 @@ type BurnMintTokenPoolRemotePoolSetIterator struct { fail error } -func (it *BurnMintTokenPoolRemotePoolSetIterator) Next() bool { +func (it *BurnMintTokenPoolRemotePoolRemovedIterator) Next() bool { if it.fail != nil { return false @@ -2224,7 +2524,7 @@ func (it *BurnMintTokenPoolRemotePoolSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BurnMintTokenPoolRemotePoolSet) + it.Event = new(BurnMintTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2239,7 +2539,7 @@ func (it *BurnMintTokenPoolRemotePoolSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(BurnMintTokenPoolRemotePoolSet) + it.Event = new(BurnMintTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2254,44 +2554,43 @@ func (it *BurnMintTokenPoolRemotePoolSetIterator) Next() bool { } } -func (it *BurnMintTokenPoolRemotePoolSetIterator) Error() error { +func (it *BurnMintTokenPoolRemotePoolRemovedIterator) Error() error { return it.fail } -func (it *BurnMintTokenPoolRemotePoolSetIterator) Close() error { +func (it *BurnMintTokenPoolRemotePoolRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type BurnMintTokenPoolRemotePoolSet struct { +type BurnMintTokenPoolRemotePoolRemoved struct { RemoteChainSelector uint64 - PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolSetIterator, error) { +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolRemovedIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnMintTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _BurnMintTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } - return &BurnMintTokenPoolRemotePoolSetIterator{contract: _BurnMintTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil + return &BurnMintTokenPoolRemotePoolRemovedIterator{contract: _BurnMintTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil } -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnMintTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _BurnMintTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2301,8 +2600,8 @@ func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolSet(opts *bi select { case log := <-logs: - event := new(BurnMintTokenPoolRemotePoolSet) - if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + event := new(BurnMintTokenPoolRemotePoolRemoved) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return err } event.Raw = log @@ -2323,9 +2622,9 @@ func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) WatchRemotePoolSet(opts *bi }), nil } -func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*BurnMintTokenPoolRemotePoolSet, error) { - event := new(BurnMintTokenPoolRemotePoolSet) - if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { +func (_BurnMintTokenPool *BurnMintTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*BurnMintTokenPoolRemotePoolRemoved, error) { + event := new(BurnMintTokenPoolRemotePoolRemoved) + if err := _BurnMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return nil, err } event.Raw = log @@ -2591,10 +2890,14 @@ func (_BurnMintTokenPool *BurnMintTokenPool) ParseLog(log types.Log) (generated. return _BurnMintTokenPool.ParseOwnershipTransferRequested(log) case _BurnMintTokenPool.abi.Events["OwnershipTransferred"].ID: return _BurnMintTokenPool.ParseOwnershipTransferred(log) + case _BurnMintTokenPool.abi.Events["RateLimitAdminSet"].ID: + return _BurnMintTokenPool.ParseRateLimitAdminSet(log) case _BurnMintTokenPool.abi.Events["Released"].ID: return _BurnMintTokenPool.ParseReleased(log) - case _BurnMintTokenPool.abi.Events["RemotePoolSet"].ID: - return _BurnMintTokenPool.ParseRemotePoolSet(log) + case _BurnMintTokenPool.abi.Events["RemotePoolAdded"].ID: + return _BurnMintTokenPool.ParseRemotePoolAdded(log) + case _BurnMintTokenPool.abi.Events["RemotePoolRemoved"].ID: + return _BurnMintTokenPool.ParseRemotePoolRemoved(log) case _BurnMintTokenPool.abi.Events["RouterUpdated"].ID: return _BurnMintTokenPool.ParseRouterUpdated(log) case _BurnMintTokenPool.abi.Events["TokensConsumed"].ID: @@ -2649,12 +2952,20 @@ func (BurnMintTokenPoolOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (BurnMintTokenPoolRateLimitAdminSet) Topic() common.Hash { + return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174") +} + func (BurnMintTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (BurnMintTokenPoolRemotePoolSet) Topic() common.Hash { - return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +func (BurnMintTokenPoolRemotePoolAdded) Topic() common.Hash { + return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") +} + +func (BurnMintTokenPoolRemotePoolRemoved) Topic() common.Hash { + return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") } func (BurnMintTokenPoolRouterUpdated) Topic() common.Hash { @@ -2680,7 +2991,7 @@ type BurnMintTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) + GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2692,6 +3003,10 @@ type BurnMintTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) + GetTokenDecimals(opts *bind.CallOpts) (uint8, error) + + IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) + IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -2704,20 +3019,22 @@ type BurnMintTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) - SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -2788,17 +3105,29 @@ type BurnMintTokenPoolInterface interface { ParseOwnershipTransferred(log types.Log) (*BurnMintTokenPoolOwnershipTransferred, error) + FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnMintTokenPoolRateLimitAdminSetIterator, error) + + WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRateLimitAdminSet) (event.Subscription, error) + + ParseRateLimitAdminSet(log types.Log) (*BurnMintTokenPoolRateLimitAdminSet, error) + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnMintTokenPoolReleasedIterator, error) WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) ParseReleased(log types.Log) (*BurnMintTokenPoolReleased, error) - FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolSetIterator, error) + FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolAddedIterator, error) + + WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolAdded(log types.Log) (*BurnMintTokenPoolRemotePoolAdded, error) + + FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnMintTokenPoolRemotePoolRemovedIterator, error) - WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolSet(log types.Log) (*BurnMintTokenPoolRemotePoolSet, error) + ParseRemotePoolRemoved(log types.Log) (*BurnMintTokenPoolRemotePoolRemoved, error) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnMintTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go index 5ce5bf9f1d..7315989c07 100644 --- a/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go +++ b/core/gethwrappers/ccip/generated/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go @@ -74,23 +74,22 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - Allowed bool - RemotePoolAddress []byte + RemotePoolAddresses [][]byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var BurnWithFromMintTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b5060405162004508380380620045088339810160408190526200003491620008c0565b8383838333806000816200008f5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c257620000c2816200018f565b5050506001600160a01b0384161580620000e357506001600160a01b038116155b80620000f657506001600160a01b038216155b1562000115576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c05262000168576040805160008152602081019091526200016890846200023a565b5062000185925050506001600160a01b0385163060001962000397565b5050505062000afc565b336001600160a01b03821603620001e95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000086565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200025b576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002e65760008382815181106200027f576200027f620009d0565b60209081029190910101519050620002996002826200047d565b15620002dc576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200025e565b5060005b8151811015620003925760008282815181106200030b576200030b620009d0565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000337575062000389565b620003446002826200049d565b1562000387576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002ea565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620003e9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200040f9190620009e6565b6200041b919062000a16565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200047791869190620004b416565b50505050565b600062000494836001600160a01b03841662000585565b90505b92915050565b600062000494836001600160a01b03841662000689565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000503906001600160a01b038516908490620006db565b80519091501562000392578080602001905181019062000524919062000a2c565b620003925760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000086565b600081815260018301602052604081205480156200067e576000620005ac60018362000a57565b8554909150600090620005c29060019062000a57565b90508082146200062e576000866000018281548110620005e657620005e6620009d0565b90600052602060002001549050808760000184815481106200060c576200060c620009d0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000642576200064262000a6d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000497565b600091505062000497565b6000818152600183016020526040812054620006d25750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000497565b50600062000497565b6060620006ec8484600085620006f4565b949350505050565b606082471015620007575760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000086565b600080866001600160a01b0316858760405162000775919062000aa9565b60006040518083038185875af1925050503d8060008114620007b4576040519150601f19603f3d011682016040523d82523d6000602084013e620007b9565b606091505b509092509050620007cd87838387620007d8565b979650505050505050565b606083156200084c57825160000362000844576001600160a01b0385163b620008445760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000086565b5081620006ec565b620006ec8383815115620008635781518083602001fd5b8060405162461bcd60e51b815260040162000086919062000ac7565b6001600160a01b03811681146200089557600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b8051620008bb816200087f565b919050565b60008060008060808587031215620008d757600080fd5b8451620008e4816200087f565b602086810151919550906001600160401b03808211156200090457600080fd5b818801915088601f8301126200091957600080fd5b8151818111156200092e576200092e62000898565b8060051b604051601f19603f8301168101818110858211171562000956576200095662000898565b60405291825284820192508381018501918b8311156200097557600080fd5b938501935b828510156200099e576200098e85620008ae565b845293850193928501926200097a565b809850505050505050620009b560408601620008ae565b9150620009c560608601620008ae565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b600060208284031215620009f957600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000497576200049762000a00565b60006020828403121562000a3f57600080fd5b8151801515811462000a5057600080fd5b9392505050565b8181038181111562000497576200049762000a00565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000aa057818101518382015260200162000a86565b50506000910152565b6000825162000abd81846020870162000a83565b9190910192915050565b602081526000825180602084015262000ae881604085016020870162000a83565b601f01601f19169190910160400192915050565b60805160a05160c05161398f62000b79600039600081816104da0152818161177401526121580152600081816104b4015281816115a50152611a2a0152600081816102360152818161028b015281816106dd015281816114c50152818161194a01528181611b42015281816120ee0152612343015261398f6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80639a4575b9116100ee578063c4bffe2b11610097578063db6327dc11610071578063db6327dc1461049f578063dc0bd971146104b2578063e0351e13146104d8578063f2fde38b146104fe57600080fd5b8063c4bffe2b14610464578063c75eea9c14610479578063cf7401f31461048c57600080fd5b8063b0f479a1116100c8578063b0f479a114610420578063b79465801461043e578063c0d786551461045157600080fd5b80639a4575b91461037c578063a7cd63b71461039c578063af58d59f146103b157600080fd5b806354c8a4f31161015b57806379ba50971161013557806379ba5097146103305780637d54534e146103385780638926f54f1461034b5780638da5cb5b1461035e57600080fd5b806354c8a4f3146102ea5780636d3d1a58146102ff57806378a010b21461031d57600080fd5b806321df0da71161018c57806321df0da714610234578063240028e81461027b57806339077537146102c857600080fd5b806301ffc9a7146101b35780630a2fd493146101db578063181f5a77146101fb575b600080fd5b6101c66101c1366004612ae6565b610511565b60405190151581526020015b60405180910390f35b6101ee6101e9366004612b45565b6105f6565b6040516101d29190612bc4565b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e300060208201526101ee565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d2565b6101c6610289366004612c04565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b6102db6102d6366004612c21565b6106a6565b604051905181526020016101d2565b6102fd6102f8366004612ca9565b61082c565b005b60085473ffffffffffffffffffffffffffffffffffffffff16610256565b6102fd61032b366004612d15565b6108a7565b6102fd610a1b565b6102fd610346366004612c04565b610b18565b6101c6610359366004612b45565b610b67565b60005473ffffffffffffffffffffffffffffffffffffffff16610256565b61038f61038a366004612d98565b610b7e565b6040516101d29190612dd3565b6103a4610c25565b6040516101d29190612e33565b6103c46103bf366004612b45565b610c36565b6040516101d2919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610256565b6101ee61044c366004612b45565b610d0b565b6102fd61045f366004612c04565b610d36565b61046c610e11565b6040516101d29190612e8d565b6103c4610487366004612b45565b610ec9565b6102fd61049a366004612ff5565b610f9b565b6102fd6104ad36600461303a565b611024565b7f0000000000000000000000000000000000000000000000000000000000000000610256565b7f00000000000000000000000000000000000000000000000000000000000000006101c6565b6102fd61050c366004612c04565b6114aa565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806105a457507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806105f057507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906106219061307c565b80601f016020809104026020016040519081016040528092919081815260200182805461064d9061307c565b801561069a5780601f1061066f5761010080835404028352916020019161069a565b820191906000526020600020905b81548152906001019060200180831161067d57829003601f168201915b50505050509050919050565b6040805160208101909152600081526106c66106c18361317a565b6114be565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107126060850160408601612c04565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260608501356024820152604401600060405180830381600087803b15801561078257600080fd5b505af1158015610796573d6000803e3d6000fd5b506107ab925050506060830160408401612c04565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f0846060013560405161080d91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6108346116ef565b6108a18484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061177292505050565b50505050565b6108af6116ef565b6108b883610b67565b6108ff576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b67ffffffffffffffff8316600090815260076020526040812060040180546109269061307c565b80601f01602080910402602001604051908101604052809291908181526020018280546109529061307c565b801561099f5780601f106109745761010080835404028352916020019161099f565b820191906000526020600020905b81548152906001019060200180831161098257829003601f168201915b5050505067ffffffffffffffff86166000908152600760205260409020919250506004016109ce8385836132bf565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610a0d939291906133d9565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610a9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016108f6565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b206116ef565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60006105f0600567ffffffffffffffff8416611928565b6040805180820190915260608082526020820152610ba3610b9e8361343d565b611943565b610bb08260600135611b0d565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610c0a84602001602081019061044c9190612b45565b81526040805160208181019092526000815291015292915050565b6060610c316002611bb6565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526105f090611bc3565b67ffffffffffffffff811660009081526007602052604090206005018054606091906106219061307c565b610d3e6116ef565b73ffffffffffffffffffffffffffffffffffffffff8116610d8b576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b60606000610e1f6005611bb6565b90506000815167ffffffffffffffff811115610e3d57610e3d612ecf565b604051908082528060200260200182016040528015610e66578160200160208202803683370190505b50905060005b8251811015610ec257828181518110610e8757610e876134df565b6020026020010151828281518110610ea157610ea16134df565b67ffffffffffffffff90921660209283029190910190910152600101610e6c565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526105f090611bc3565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590610fdb575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611014576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b61101f838383611c75565b505050565b61102c6116ef565b60005b8181101561101f57600083838381811061104b5761104b6134df565b905060200281019061105d919061350e565b6110669061354c565b905061107b8160800151826020015115611d5f565b61108e8160a00151826020015115611d5f565b80602001511561138a5780516110b09060059067ffffffffffffffff16611e98565b6110f55780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f6565b604081015151158061110a5750606081015151155b15611141576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906113229082613600565b50606082015160058201906113379082613600565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061137d949392919061371a565b60405180910390a16114a1565b80516113a29060059067ffffffffffffffff16611ea4565b6113e75780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016108f6565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906114506004830182612a98565b61145e600583016000612a98565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b5060010161102f565b6114b26116ef565b6114bb81611eb0565b50565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146115535760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f6565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611601573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162591906137b3565b1561165c576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116698160200151611fa5565b600061167882602001516105f6565b905080516000148061169c575080805190602001208260a001518051906020012014155b156116d9578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016108f69190612bc4565b6116eb826020015183606001516120cb565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611770576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016108f6565b565b7f00000000000000000000000000000000000000000000000000000000000000006117c9576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561185f5760008382815181106117e9576117e96134df565b6020026020010151905061180781600261211290919063ffffffff16565b156118565760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016117cc565b5060005b815181101561101f576000828281518110611880576118806134df565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036118c45750611920565b6118cf600282612134565b1561191e5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611863565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146119d85760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016108f6565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611a86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aaa91906137b3565b15611ae1576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611aee8160400151612156565b611afb81602001516121d5565b6114bb81602001518260600151612323565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b5050505050565b6060600061193c83612367565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611c5182606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611c3591906137ff565b85608001516fffffffffffffffffffffffffffffffff166123c2565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b611c7e83610b67565b611cc0576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016108f6565b611ccb826000611d5f565b67ffffffffffffffff83166000908152600760205260409020611cee90836123ec565b611cf9816000611d5f565b67ffffffffffffffff83166000908152600760205260409020611d1f90600201826123ec565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051611d5293929190613812565b60405180910390a1505050565b815115611e265781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580611db5575060408201516fffffffffffffffffffffffffffffffff16155b15611dee57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016108f69190613895565b80156116eb576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580611e5f575060208201516fffffffffffffffffffffffffffffffff1615155b156116eb57816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016108f69190613895565b600061193c838361258e565b600061193c83836125dd565b3373ffffffffffffffffffffffffffffffffffffffff821603611f2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016108f6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611fae81610b67565b611ff0576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f6565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561206f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061209391906137b3565b6114bb576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b67ffffffffffffffff821660009081526007602052604090206116eb90600201827f00000000000000000000000000000000000000000000000000000000000000006126d0565b600061193c8373ffffffffffffffffffffffffffffffffffffffff84166125dd565b600061193c8373ffffffffffffffffffffffffffffffffffffffff841661258e565b7f0000000000000000000000000000000000000000000000000000000000000000156114bb57612187600282612a53565b6114bb576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016108f6565b6121de81610b67565b612220576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016108f6565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612299573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bd91906138d1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146114bb576040517f728fe07b0000000000000000000000000000000000000000000000000000000081523360048201526024016108f6565b67ffffffffffffffff821660009081526007602052604090206116eb90827f00000000000000000000000000000000000000000000000000000000000000006126d0565b60608160000180548060200260200160405190810160405280929190818152602001828054801561069a57602002820191906000526020600020905b8154815260200190600101908083116123a35750505050509050919050565b60006123e1856123d284866138ee565b6123dc9087613905565b612a82565b90505b949350505050565b815460009061241590700100000000000000000000000000000000900463ffffffff16426137ff565b905080156124b7576001830154835461245d916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166123c2565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546124dd916fffffffffffffffffffffffffffffffff9081169116612a82565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990611d52908490613895565b60008181526001830160205260408120546125d5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556105f0565b5060006105f0565b600081815260018301602052604081205480156126c65760006126016001836137ff565b8554909150600090612615906001906137ff565b905080821461267a576000866000018281548110612635576126356134df565b9060005260206000200154905080876000018481548110612658576126586134df565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268b5761268b613918565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506105f0565b60009150506105f0565b825474010000000000000000000000000000000000000000900460ff1615806126f7575081155b1561270157505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061274790700100000000000000000000000000000000900463ffffffff16426137ff565b905080156128075781831115612789576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546127c39083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166123c2565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156128be5773ffffffffffffffffffffffffffffffffffffffff8416612866576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016108f6565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016108f6565b848310156129d15760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1690600090829061290290826137ff565b61290c878a6137ff565b6129169190613905565b6129209190613947565b905073ffffffffffffffffffffffffffffffffffffffff8616612979576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016108f6565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016108f6565b6129db85846137ff565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561193c565b6000818310612a91578161193c565b5090919050565b508054612aa49061307c565b6000825580601f10612ab4575050565b601f0160209004906000526020600020908101906114bb91905b80821115612ae25760008155600101612ace565b5090565b600060208284031215612af857600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461193c57600080fd5b803567ffffffffffffffff81168114612b4057600080fd5b919050565b600060208284031215612b5757600080fd5b61193c82612b28565b6000815180845260005b81811015612b8657602081850181015186830182015201612b6a565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061193c6020830184612b60565b73ffffffffffffffffffffffffffffffffffffffff811681146114bb57600080fd5b8035612b4081612bd7565b600060208284031215612c1657600080fd5b813561193c81612bd7565b600060208284031215612c3357600080fd5b813567ffffffffffffffff811115612c4a57600080fd5b8201610100818503121561193c57600080fd5b60008083601f840112612c6f57600080fd5b50813567ffffffffffffffff811115612c8757600080fd5b6020830191508360208260051b8501011115612ca257600080fd5b9250929050565b60008060008060408587031215612cbf57600080fd5b843567ffffffffffffffff80821115612cd757600080fd5b612ce388838901612c5d565b90965094506020870135915080821115612cfc57600080fd5b50612d0987828801612c5d565b95989497509550505050565b600080600060408486031215612d2a57600080fd5b612d3384612b28565b9250602084013567ffffffffffffffff80821115612d5057600080fd5b818601915086601f830112612d6457600080fd5b813581811115612d7357600080fd5b876020828501011115612d8557600080fd5b6020830194508093505050509250925092565b600060208284031215612daa57600080fd5b813567ffffffffffffffff811115612dc157600080fd5b820160a0818503121561193c57600080fd5b602081526000825160406020840152612def6060840182612b60565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612e2a8282612b60565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8157835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612e4f565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015612e8157835167ffffffffffffffff1683529284019291840191600101612ea9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff81118282101715612f2257612f22612ecf565b60405290565b60405160c0810167ffffffffffffffff81118282101715612f2257612f22612ecf565b80151581146114bb57600080fd5b8035612b4081612f4b565b80356fffffffffffffffffffffffffffffffff81168114612b4057600080fd5b600060608284031215612f9657600080fd5b6040516060810181811067ffffffffffffffff82111715612fb957612fb9612ecf565b6040529050808235612fca81612f4b565b8152612fd860208401612f64565b6020820152612fe960408401612f64565b60408201525092915050565b600080600060e0848603121561300a57600080fd5b61301384612b28565b92506130228560208601612f84565b91506130318560808601612f84565b90509250925092565b6000806020838503121561304d57600080fd5b823567ffffffffffffffff81111561306457600080fd5b61307085828601612c5d565b90969095509350505050565b600181811c9082168061309057607f821691505b6020821081036130c9577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126130e057600080fd5b813567ffffffffffffffff808211156130fb576130fb612ecf565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561314157613141612ecf565b8160405283815286602085880101111561315a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000610100823603121561318d57600080fd5b613195612efe565b823567ffffffffffffffff808211156131ad57600080fd5b6131b9368387016130cf565b83526131c760208601612b28565b60208401526131d860408601612bf9565b6040840152606085013560608401526131f360808601612bf9565b608084015260a085013591508082111561320c57600080fd5b613218368387016130cf565b60a084015260c085013591508082111561323157600080fd5b61323d368387016130cf565b60c084015260e085013591508082111561325657600080fd5b50613263368286016130cf565b60e08301525092915050565b601f82111561101f576000816000526020600020601f850160051c810160208610156132985750805b601f850160051c820191505b818110156132b7578281556001016132a4565b505050505050565b67ffffffffffffffff8311156132d7576132d7612ecf565b6132eb836132e5835461307c565b8361326f565b6000601f84116001811461333d57600085156133075750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355611baf565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561338c578685013582556020948501946001909201910161336c565b50868210156133c7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555050505050565b6040815260006133ec6040830186612b60565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a0823603121561344f57600080fd5b60405160a0810167ffffffffffffffff828210818311171561347357613473612ecf565b81604052843591508082111561348857600080fd5b50613495368286016130cf565b8252506134a460208401612b28565b602082015260408301356134b781612bd7565b60408201526060838101359082015260808301356134d481612bd7565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec183360301811261354257600080fd5b9190910192915050565b6000610140823603121561355f57600080fd5b613567612f28565b61357083612b28565b815261357e60208401612f59565b6020820152604083013567ffffffffffffffff8082111561359e57600080fd5b6135aa368387016130cf565b604084015260608501359150808211156135c357600080fd5b506135d0368286016130cf565b6060830152506135e33660808501612f84565b60808201526135f53660e08501612f84565b60a082015292915050565b815167ffffffffffffffff81111561361a5761361a612ecf565b61362e81613628845461307c565b8461326f565b602080601f831160018114613681576000841561364b5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556132b7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156136ce578886015182559484019460019091019084016136af565b508582101561370a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261373e81840187612b60565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff908116606087015290870151166080850152915061377c9050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612e2a565b6000602082840312156137c557600080fd5b815161193c81612f4b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156105f0576105f06137d0565b67ffffffffffffffff8416815260e0810161385e60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c08301526123e4565b606081016105f082848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b6000602082840312156138e357600080fd5b815161193c81612bd7565b80820281158282048414176105f0576105f06137d0565b808201808211156105f0576105f06137d0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008261397d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIBurnMintERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162004c5c38038062004c5c833981016040819052620000359162000918565b8484848484336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f8162000206565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e9181019062000a3a565b60015b1562000192578060ff168560ff161462000190576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dc57604080516000815260208101909152620001dc908462000280565b50620001fb935050506001600160a01b038716905030600019620003dd565b505050505062000b84565b336001600160a01b038216036200023057604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e051620002a1576040516335f4a7b360e01b815260040160405180910390fd5b60005b82518110156200032c576000838281518110620002c557620002c562000a58565b60209081029190910101519050620002df600282620004c3565b1562000322576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620002a4565b5060005b8151811015620003d857600082828151811062000351576200035162000a58565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200037d5750620003cf565b6200038a600282620004e3565b15620003cd576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000330565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa1580156200042f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000455919062000a6e565b62000461919062000a9e565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152919250620004bd91869190620004fa16565b50505050565b6000620004da836001600160a01b038416620005cb565b90505b92915050565b6000620004da836001600160a01b038416620006cf565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649082015260009062000549906001600160a01b03851690849062000721565b805190915015620003d857808060200190518101906200056a919062000ab4565b620003d85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000187565b60008181526001830160205260408120548015620006c4576000620005f260018362000adf565b8554909150600090620006089060019062000adf565b9050808214620006745760008660000182815481106200062c576200062c62000a58565b906000526020600020015490508087600001848154811062000652576200065262000a58565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000688576200068862000af5565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620004dd565b6000915050620004dd565b60008181526001830160205260408120546200071857508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620004dd565b506000620004dd565b60606200073284846000856200073a565b949350505050565b6060824710156200079d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000187565b600080866001600160a01b03168587604051620007bb919062000b31565b60006040518083038185875af1925050503d8060008114620007fa576040519150601f19603f3d011682016040523d82523d6000602084013e620007ff565b606091505b50909250905062000813878383876200081e565b979650505050505050565b60608315620008925782516000036200088a576001600160a01b0385163b6200088a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000187565b508162000732565b620007328383815115620008a95781518083602001fd5b8060405162461bcd60e51b815260040162000187919062000b4f565b6001600160a01b0381168114620008db57600080fd5b50565b805160ff81168114620008f057600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620008f081620008c5565b600080600080600060a086880312156200093157600080fd5b85516200093e81620008c5565b945060206200094f878201620008de565b60408801519095506001600160401b03808211156200096d57600080fd5b818901915089601f8301126200098257600080fd5b815181811115620009975762000997620008f5565b8060051b604051601f19603f83011681018181108582111715620009bf57620009bf620008f5565b60405291825284820192508381018501918c831115620009de57600080fd5b938501935b8285101562000a0757620009f7856200090b565b84529385019392850192620009e3565b80985050505050505062000a1e606087016200090b565b915062000a2e608087016200090b565b90509295509295909350565b60006020828403121562000a4d57600080fd5b620004da82620008de565b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000a8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115620004dd57620004dd62000a88565b60006020828403121562000ac757600080fd5b8151801515811462000ad857600080fd5b9392505050565b81810381811115620004dd57620004dd62000a88565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000b2857818101518382015260200162000b0e565b50506000910152565b6000825162000b4581846020870162000b0b565b9190910192915050565b602081526000825180602084015262000b7081604085016020870162000b0b565b601f01601f19169190910160400192915050565b60805160a05160c05160e05161402762000c356000396000818161054801528181611d7b01526127cc0152600081816105220152818161189801526120670152600081816102d901528181610ba201528181611a4101528181611afb01528181611b2f01528181611b6201528181611bc701528181611c200152611cc20152600081816102400152818161029501528181610701015281816121ea0152818161276201526129b701526140276000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80639a4575b911610104578063c0d78655116100a2578063dc0bd97111610071578063dc0bd97114610520578063e0351e1314610546578063e8a1da171461056c578063f2fde38b1461057f57600080fd5b8063c0d78655146104d2578063c4bffe2b146104e5578063c75eea9c146104fa578063cf7401f31461050d57600080fd5b8063acfecf91116100de578063acfecf911461041f578063af58d59f14610432578063b0f479a1146104a1578063b7946580146104bf57600080fd5b80639a4575b9146103ca578063a42a7b8b146103ea578063a7cd63b71461040a57600080fd5b806354c8a4f31161017157806379ba50971161014b57806379ba50971461037e5780637d54534e146103865780638926f54f146103995780638da5cb5b146103ac57600080fd5b806354c8a4f31461033857806362ddd3c41461034d5780636d3d1a581461036057600080fd5b8063240028e8116101ad578063240028e81461028557806324f65ee7146102d257806339077537146103035780634c5ef0ed1461032557600080fd5b806301ffc9a7146101d4578063181f5a77146101fc57806321df0da71461023e575b600080fd5b6101e76101e2366004613177565b610592565b60405190151581526020015b60405180910390f35b60408051808201909152601f81527f4275726e5769746846726f6d4d696e74546f6b656e506f6f6c20312e352e310060208201525b6040516101f3919061321d565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f3565b6101e7610293366004613252565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f00000000000000000000000000000000000000000000000000000000000000001681526020016101f3565b61031661031136600461326f565b610677565b604051905181526020016101f3565b6101e76103333660046132c8565b610846565b61034b610346366004613397565b610890565b005b61034b61035b3660046132c8565b61090b565b60095473ffffffffffffffffffffffffffffffffffffffff16610260565b61034b6109a8565b61034b610394366004613252565b610a76565b6101e76103a7366004613403565b610af7565b60015473ffffffffffffffffffffffffffffffffffffffff16610260565b6103dd6103d836600461341e565b610b0e565b6040516101f39190613459565b6103fd6103f8366004613403565b610be7565b6040516101f391906134b0565b610412610d52565b6040516101f39190613532565b61034b61042d3660046132c8565b610d63565b610445610440366004613403565b610e7b565b6040516101f3919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff16610260565b6102316104cd366004613403565b610f50565b61034b6104e0366004613252565b611000565b6104ed6110db565b6040516101f3919061358c565b610445610508366004613403565b611193565b61034b61051b366004613714565b611265565b7f0000000000000000000000000000000000000000000000000000000000000000610260565b7f00000000000000000000000000000000000000000000000000000000000000006101e7565b61034b61057a366004613397565b6112e9565b61034b61058d366004613252565b6117fb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061062557507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061067157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b60408051602081019091526000815261068f8261180f565b60006106e860608401356106e36106a960c0870187613759565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a3392505050565b611af7565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166340c10f196107366060860160408701613252565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff909116600482015260248101849052604401600060405180830381600087803b1580156107a357600080fd5b505af11580156107b7573d6000803e3d6000fd5b506107cc925050506060840160408501613252565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08360405161082a91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610888838360405161085b9291906137be565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190611d0b565b949350505050565b610898611d26565b61090584848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611d7992505050565b50505050565b610913611d26565b61091c83610af7565b610963576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6109a38383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f2f92505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146109f9576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a7e611d26565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b6000610671600567ffffffffffffffff8416611d0b565b6040805180820190915260608082526020820152610b2b82612029565b610b3882606001356121b5565b6040516060830135815233907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a26040518060400160405280610b928460200160208101906104cd9190613403565b8152602001610bdf6040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610c1090600501612257565b90506000815167ffffffffffffffff811115610c2e57610c2e6135ce565b604051908082528060200260200182016040528015610c6157816020015b6060815260200190600190039081610c4c5790505b50905060005b8251811015610d4a5760086000848381518110610c8657610c866137ce565b602002602001015181526020019081526020016000208054610ca7906137fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd3906137fd565b8015610d205780601f10610cf557610100808354040283529160200191610d20565b820191906000526020600020905b815481529060010190602001808311610d0357829003601f168201915b5050505050828281518110610d3757610d376137ce565b6020908102919091010152600101610c67565b509392505050565b6060610d5e6002612257565b905090565b610d6b611d26565b610d7483610af7565b610db6576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b610df68282604051610dc99291906137be565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612264565b610e32578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161095a93929190613899565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051610e6e9291906138bd565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261067190612270565b67ffffffffffffffff81166000908152600760205260409020600401805460609190610f7b906137fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610fa7906137fd565b8015610ff45780601f10610fc957610100808354040283529160200191610ff4565b820191906000526020600020905b815481529060010190602001808311610fd757829003601f168201915b50505050509050919050565b611008611d26565b73ffffffffffffffffffffffffffffffffffffffff8116611055576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110e96005612257565b90506000815167ffffffffffffffff811115611107576111076135ce565b604051908082528060200260200182016040528015611130578160200160208202803683370190505b50905060005b825181101561118c57828181518110611151576111516137ce565b602002602001015182828151811061116b5761116b6137ce565b67ffffffffffffffff90921660209283029190910190910152600101611136565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261067190612270565b60095473ffffffffffffffffffffffffffffffffffffffff1633148015906112a5575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156112de576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b6109a3838383612322565b6112f1611d26565b60005b838110156114de576000858583818110611310576113106137ce565b90506020020160208101906113259190613403565b905061133c600567ffffffffffffffff8316612264565b61137e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b67ffffffffffffffff811660009081526007602052604081206113a390600501612257565b905060005b815181101561140f576114068282815181106113c6576113c66137ce565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161226490919063ffffffff16565b506001016113a8565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611478600483018261310a565b600582016000818161148a8282613144565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d859916945060200192506114cc915050565b60405180910390a150506001016112f4565b5060005b818110156117f45760008383838181106114fe576114fe6137ce565b905060200281019061151091906138d1565b6115199061399d565b905061152a8160600151600061240c565b6115398160800151600061240c565b806040015151600003611578576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516115909060059067ffffffffffffffff16612549565b6115d55780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161095a565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a9091029990931617179094169590951790925590920290911760038201559082015160048201906117589082613b14565b5060005b82602001515181101561179c57611794836000015184602001518381518110611787576117876137ce565b6020026020010151611f2f565b60010161175c565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c282600001518360400151846060015185608001516040516117e29493929190613c2e565b60405180910390a150506001016114e2565b5050505050565b611803611d26565b61180c81612555565b50565b61182261029360a0830160808401613252565b6118815761183660a0820160808301613252565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161095a565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6118cd6040840160208501613403565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561193e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119629190613cc7565b15611999576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119b16119ac6040830160208401613403565b612619565b6119d16119c46040830160208401613403565b61033360a0840184613759565b611a16576119e260a0820182613759565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161095a9291906138bd565b61180c611a296040830160208401613403565b826060013561273f565b60008151600003611a6557507f0000000000000000000000000000000000000000000000000000000000000000919050565b8151602014611aa257816040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a919061321d565b600082806020019051810190611ab89190613ce4565b905060ff81111561067157826040517f953576f700000000000000000000000000000000000000000000000000000000815260040161095a919061321d565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1603611b2d575081610671565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff161115611c18576000611b877f000000000000000000000000000000000000000000000000000000000000000084613d2c565b9050604d8160ff161115611bfb576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161095a565b611c0681600a613e65565b611c109085613e74565b915050610671565b6000611c44837f0000000000000000000000000000000000000000000000000000000000000000613d2c565b9050604d8160ff161180611c8b5750611c5e81600a613e65565b611c88907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff613e74565b84115b15611cf6576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f00000000000000000000000000000000000000000000000000000000000000001660248201526044810185905260640161095a565b611d0181600a613e65565b6108889085613eaf565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611d77576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f0000000000000000000000000000000000000000000000000000000000000000611dd0576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611e66576000838281518110611df057611df06137ce565b60200260200101519050611e0e81600261278690919063ffffffff16565b15611e5d5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611dd3565b5060005b81518110156109a3576000828281518110611e8757611e876137ce565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611ecb5750611f27565b611ed66002826127a8565b15611f255760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611e6a565b8051600003611f6a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff8416600090815260079092526040909120611f9c9060050182612549565b611fd65782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161095a929190613ec6565b6000818152600860205260409020611fee8382613b14565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea83604051610e6e919061321d565b61203c61029360a0830160808401613252565b6120505761183660a0820160808301613252565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61209c6040840160208501613403565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121319190613cc7565b15612168576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61218061217b6060830160408401613252565b6127ca565b6121986121936040830160208401613403565b612849565b61180c6121ab6040830160208401613403565b8260600135612997565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018290527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639dc29fac90604401600060405180830381600087803b15801561224357600080fd5b505af11580156117f4573d6000803e3d6000fd5b60606000611d1f836129db565b6000611d1f8383612a36565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526122fe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426122e29190613ee9565b85608001516fffffffffffffffffffffffffffffffff16612b29565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61232b83610af7565b61236d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161095a565b61237882600061240c565b67ffffffffffffffff8316600090815260076020526040902061239b9083612b51565b6123a681600061240c565b67ffffffffffffffff831660009081526007602052604090206123cc9060020182612b51565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516123ff93929190613efc565b60405180910390a1505050565b8151156124d75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612462575060408201516fffffffffffffffffffffffffffffffff16155b1561249b57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161095a9190613f7f565b80156124d3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612510575060208201516fffffffffffffffffffffffffffffffff1615155b156124d357816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161095a9190613f7f565b6000611d1f8383612cf3565b3373ffffffffffffffffffffffffffffffffffffffff8216036125a4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b61262281610af7565b612664576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa1580156126e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127079190613cc7565b61180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206124d390600201827f0000000000000000000000000000000000000000000000000000000000000000612d42565b6000611d1f8373ffffffffffffffffffffffffffffffffffffffff8416612a36565b6000611d1f8373ffffffffffffffffffffffffffffffffffffffff8416612cf3565b7f00000000000000000000000000000000000000000000000000000000000000001561180c576127fb6002826130c5565b61180c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161095a565b61285281610af7565b612894576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161095a565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa15801561290d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129319190613fbb565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461180c576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161095a565b67ffffffffffffffff821660009081526007602052604090206124d390827f0000000000000000000000000000000000000000000000000000000000000000612d42565b606081600001805480602002602001604051908101604052809291908181526020018280548015610ff457602002820191906000526020600020905b815481526020019060010190808311612a175750505050509050919050565b60008181526001830160205260408120548015612b1f576000612a5a600183613ee9565b8554909150600090612a6e90600190613ee9565b9050808214612ad3576000866000018281548110612a8e57612a8e6137ce565b9060005260206000200154905080876000018481548110612ab157612ab16137ce565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ae457612ae4613fd8565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610671565b6000915050610671565b6000612b4885612b398486613eaf565b612b439087614007565b6130f4565b95945050505050565b8154600090612b7a90700100000000000000000000000000000000900463ffffffff1642613ee9565b90508015612c1c5760018301548354612bc2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612b29565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c42916fffffffffffffffffffffffffffffffff90811691166130f4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906123ff908490613f7f565b6000818152600183016020526040812054612d3a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610671565b506000610671565b825474010000000000000000000000000000000000000000900460ff161580612d69575081155b15612d7357505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612db990700100000000000000000000000000000000900463ffffffff1642613ee9565b90508015612e795781831115612dfb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612e359083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612b29565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612f305773ffffffffffffffffffffffffffffffffffffffff8416612ed8576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161095a565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161095a565b848310156130435760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f749082613ee9565b612f7e878a613ee9565b612f889190614007565b612f929190613e74565b905073ffffffffffffffffffffffffffffffffffffffff8616612feb576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161095a565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161095a565b61304d8584613ee9565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611d1f565b60008183106131035781611d1f565b5090919050565b508054613116906137fd565b6000825580601f10613126575050565b601f01602090049060005260206000209081019061180c919061315e565b508054600082559060005260206000209081019061180c91905b5b80821115613173576000815560010161315f565b5090565b60006020828403121561318957600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611d1f57600080fd5b6000815180845260005b818110156131df576020818501810151868301820152016131c3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611d1f60208301846131b9565b73ffffffffffffffffffffffffffffffffffffffff8116811461180c57600080fd5b60006020828403121561326457600080fd5b8135611d1f81613230565b60006020828403121561328157600080fd5b813567ffffffffffffffff81111561329857600080fd5b82016101008185031215611d1f57600080fd5b803567ffffffffffffffff811681146132c357600080fd5b919050565b6000806000604084860312156132dd57600080fd5b6132e6846132ab565b9250602084013567ffffffffffffffff8082111561330357600080fd5b818601915086601f83011261331757600080fd5b81358181111561332657600080fd5b87602082850101111561333857600080fd5b6020830194508093505050509250925092565b60008083601f84011261335d57600080fd5b50813567ffffffffffffffff81111561337557600080fd5b6020830191508360208260051b850101111561339057600080fd5b9250929050565b600080600080604085870312156133ad57600080fd5b843567ffffffffffffffff808211156133c557600080fd5b6133d18883890161334b565b909650945060208701359150808211156133ea57600080fd5b506133f78782880161334b565b95989497509550505050565b60006020828403121561341557600080fd5b611d1f826132ab565b60006020828403121561343057600080fd5b813567ffffffffffffffff81111561344757600080fd5b820160a08185031215611d1f57600080fd5b60208152600082516040602084015261347560608401826131b9565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612b4882826131b9565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613525577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526135138583516131b9565b945092850192908501906001016134d9565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358057835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161354e565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561358057835167ffffffffffffffff16835292840192918401916001016135a8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613620576136206135ce565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561366d5761366d6135ce565b604052919050565b801515811461180c57600080fd5b80356fffffffffffffffffffffffffffffffff811681146132c357600080fd5b6000606082840312156136b557600080fd5b6040516060810181811067ffffffffffffffff821117156136d8576136d86135ce565b60405290508082356136e981613675565b81526136f760208401613683565b602082015261370860408401613683565b60408201525092915050565b600080600060e0848603121561372957600080fd5b613732846132ab565b925061374185602086016136a3565b915061375085608086016136a3565b90509250925092565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261378e57600080fd5b83018035915067ffffffffffffffff8211156137a957600080fd5b60200191503681900382131561339057600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c9082168061381157607f821691505b60208210810361384a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff84168152604060208201526000612b48604083018486613850565b602081526000610888602083018486613850565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261390557600080fd5b9190910192915050565b600082601f83011261392057600080fd5b813567ffffffffffffffff81111561393a5761393a6135ce565b61396b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613626565b81815284602083860101111561398057600080fd5b816020850160208301376000918101602001919091529392505050565b600061012082360312156139b057600080fd5b6139b86135fd565b6139c1836132ab565b815260208084013567ffffffffffffffff808211156139df57600080fd5b9085019036601f8301126139f257600080fd5b813581811115613a0457613a046135ce565b8060051b613a13858201613626565b9182528381018501918581019036841115613a2d57600080fd5b86860192505b83831015613a6957823585811115613a4b5760008081fd5b613a593689838a010161390f565b8352509186019190860190613a33565b8087890152505050506040860135925080831115613a8657600080fd5b5050613a943682860161390f565b604083015250613aa736606085016136a3565b6060820152613ab93660c085016136a3565b608082015292915050565b601f8211156109a3576000816000526020600020601f850160051c81016020861015613aed5750805b601f850160051c820191505b81811015613b0c57828155600101613af9565b505050505050565b815167ffffffffffffffff811115613b2e57613b2e6135ce565b613b4281613b3c84546137fd565b84613ac4565b602080601f831160018114613b955760008415613b5f5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b0c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613be257888601518255948401946001909101908401613bc3565b5085821015613c1e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613c52818401876131b9565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff9081166060870152908701511660808501529150613c909050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612b48565b600060208284031215613cd957600080fd5b8151611d1f81613675565b600060208284031215613cf657600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff828116828216039081111561067157610671613cfd565b600181815b80851115613d9e57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613d8457613d84613cfd565b80851615613d9157918102915b93841c9390800290613d4a565b509250929050565b600082613db557506001610671565b81613dc257506000610671565b8160018114613dd85760028114613de257613dfe565b6001915050610671565b60ff841115613df357613df3613cfd565b50506001821b610671565b5060208310610133831016604e8410600b8410161715613e21575081810a610671565b613e2b8383613d45565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613e5d57613e5d613cfd565b029392505050565b6000611d1f60ff841683613da6565b600082613eaa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761067157610671613cfd565b67ffffffffffffffff8316815260406020820152600061088860408301846131b9565b8181038181111561067157610671613cfd565b67ffffffffffffffff8416815260e08101613f4860208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610888565b6060810161067182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b600060208284031215613fcd57600080fd5b8151611d1f81613230565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8082018082111561067157610671613cfd56fea164736f6c6343000818000a", } var BurnWithFromMintTokenPoolABI = BurnWithFromMintTokenPoolMetaData.ABI var BurnWithFromMintTokenPoolBin = BurnWithFromMintTokenPoolMetaData.Bin -func DeployBurnWithFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnWithFromMintTokenPool, error) { +func DeployBurnWithFromMintTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, router common.Address) (common.Address, *types.Transaction, *BurnWithFromMintTokenPool, error) { parsed, err := BurnWithFromMintTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -99,7 +98,7 @@ func DeployBurnWithFromMintTokenPool(auth *bind.TransactOpts, backend bind.Contr return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnWithFromMintTokenPoolBin), backend, token, allowlist, rmnProxy, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(BurnWithFromMintTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, router) if err != nil { return common.Address{}, nil, nil, err } @@ -332,26 +331,26 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetRat return _BurnWithFromMintTokenPool.Contract.GetRateLimitAdmin(&_BurnWithFromMintTokenPool.CallOpts) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { var out []interface{} - err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) if err != nil { - return *new([]byte), err + return *new([][]byte), err } - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) return out0, err } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _BurnWithFromMintTokenPool.Contract.GetRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _BurnWithFromMintTokenPool.Contract.GetRemotePools(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _BurnWithFromMintTokenPool.Contract.GetRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _BurnWithFromMintTokenPool.Contract.GetRemotePools(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector) } func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -464,6 +463,50 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetTok return _BurnWithFromMintTokenPool.Contract.GetToken(&_BurnWithFromMintTokenPool.CallOpts) } +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "getTokenDecimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) GetTokenDecimals() (uint8, error) { + return _BurnWithFromMintTokenPool.Contract.GetTokenDecimals(&_BurnWithFromMintTokenPool.CallOpts) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { + return _BurnWithFromMintTokenPool.Contract.GetTokenDecimals(&_BurnWithFromMintTokenPool.CallOpts) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + var out []interface{} + err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _BurnWithFromMintTokenPool.Contract.IsRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _BurnWithFromMintTokenPool.Contract.IsRemotePool(&_BurnWithFromMintTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _BurnWithFromMintTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -586,6 +629,18 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Ac return _BurnWithFromMintTokenPool.Contract.AcceptOwnership(&_BurnWithFromMintTokenPool.TransactOpts) } +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.AddRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.AddRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -598,16 +653,16 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Ap return _BurnWithFromMintTokenPool.Contract.ApplyAllowListUpdates(&_BurnWithFromMintTokenPool.TransactOpts, removes, adds) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", chains) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, chains) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, chains) +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.ApplyChainUpdates(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -634,6 +689,18 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Re return _BurnWithFromMintTokenPool.Contract.ReleaseOrMint(&_BurnWithFromMintTokenPool.TransactOpts, releaseOrMintIn) } +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.RemoveRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _BurnWithFromMintTokenPool.Contract.RemoveRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -658,18 +725,6 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) Se return _BurnWithFromMintTokenPool.Contract.SetRateLimitAdmin(&_BurnWithFromMintTokenPool.TransactOpts, rateLimitAdmin) } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.SetRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _BurnWithFromMintTokenPool.Contract.SetRemotePool(&_BurnWithFromMintTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _BurnWithFromMintTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2066,6 +2121,123 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseOwners return event, nil } +type BurnWithFromMintTokenPoolRateLimitAdminSetIterator struct { + Event *BurnWithFromMintTokenPoolRateLimitAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolRateLimitAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BurnWithFromMintTokenPoolRateLimitAdminSetIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolRateLimitAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolRateLimitAdminSet struct { + RateLimitAdmin common.Address + Raw types.Log +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolRateLimitAdminSetIterator, error) { + + logs, sub, err := _BurnWithFromMintTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolRateLimitAdminSetIterator{contract: _BurnWithFromMintTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRateLimitAdminSet) (event.Subscription, error) { + + logs, sub, err := _BurnWithFromMintTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnWithFromMintTokenPoolRateLimitAdminSet) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*BurnWithFromMintTokenPoolRateLimitAdminSet, error) { + event := new(BurnWithFromMintTokenPoolRateLimitAdminSet) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type BurnWithFromMintTokenPoolReleasedIterator struct { Event *BurnWithFromMintTokenPoolReleased @@ -2203,8 +2375,136 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseReleas return event, nil } -type BurnWithFromMintTokenPoolRemotePoolSetIterator struct { - Event *BurnWithFromMintTokenPoolRemotePoolSet +type BurnWithFromMintTokenPoolRemotePoolAddedIterator struct { + Event *BurnWithFromMintTokenPoolRemotePoolAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(BurnWithFromMintTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Error() error { + return it.fail +} + +func (it *BurnWithFromMintTokenPoolRemotePoolAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type BurnWithFromMintTokenPoolRemotePoolAdded struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolAddedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnWithFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &BurnWithFromMintTokenPoolRemotePoolAddedIterator{contract: _BurnWithFromMintTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _BurnWithFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(BurnWithFromMintTokenPoolRemotePoolAdded) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolAdded, error) { + event := new(BurnWithFromMintTokenPoolRemotePoolAdded) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type BurnWithFromMintTokenPoolRemotePoolRemovedIterator struct { + Event *BurnWithFromMintTokenPoolRemotePoolRemoved contract *bind.BoundContract event string @@ -2215,7 +2515,7 @@ type BurnWithFromMintTokenPoolRemotePoolSetIterator struct { fail error } -func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Next() bool { +func (it *BurnWithFromMintTokenPoolRemotePoolRemovedIterator) Next() bool { if it.fail != nil { return false @@ -2224,7 +2524,7 @@ func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BurnWithFromMintTokenPoolRemotePoolSet) + it.Event = new(BurnWithFromMintTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2239,7 +2539,7 @@ func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(BurnWithFromMintTokenPoolRemotePoolSet) + it.Event = new(BurnWithFromMintTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2254,44 +2554,43 @@ func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Next() bool { } } -func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Error() error { +func (it *BurnWithFromMintTokenPoolRemotePoolRemovedIterator) Error() error { return it.fail } -func (it *BurnWithFromMintTokenPoolRemotePoolSetIterator) Close() error { +func (it *BurnWithFromMintTokenPoolRemotePoolRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type BurnWithFromMintTokenPoolRemotePoolSet struct { +type BurnWithFromMintTokenPoolRemotePoolRemoved struct { RemoteChainSelector uint64 - PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolSetIterator, error) { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolRemovedIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnWithFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _BurnWithFromMintTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } - return &BurnWithFromMintTokenPoolRemotePoolSetIterator{contract: _BurnWithFromMintTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil + return &BurnWithFromMintTokenPoolRemotePoolRemovedIterator{contract: _BurnWithFromMintTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _BurnWithFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _BurnWithFromMintTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2301,8 +2600,8 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemote select { case log := <-logs: - event := new(BurnWithFromMintTokenPoolRemotePoolSet) - if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + event := new(BurnWithFromMintTokenPoolRemotePoolRemoved) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return err } event.Raw = log @@ -2323,9 +2622,9 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) WatchRemote }), nil } -func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolSet, error) { - event := new(BurnWithFromMintTokenPoolRemotePoolSet) - if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { +func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolRemoved, error) { + event := new(BurnWithFromMintTokenPoolRemotePoolRemoved) + if err := _BurnWithFromMintTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return nil, err } event.Raw = log @@ -2591,10 +2890,14 @@ func (_BurnWithFromMintTokenPool *BurnWithFromMintTokenPool) ParseLog(log types. return _BurnWithFromMintTokenPool.ParseOwnershipTransferRequested(log) case _BurnWithFromMintTokenPool.abi.Events["OwnershipTransferred"].ID: return _BurnWithFromMintTokenPool.ParseOwnershipTransferred(log) + case _BurnWithFromMintTokenPool.abi.Events["RateLimitAdminSet"].ID: + return _BurnWithFromMintTokenPool.ParseRateLimitAdminSet(log) case _BurnWithFromMintTokenPool.abi.Events["Released"].ID: return _BurnWithFromMintTokenPool.ParseReleased(log) - case _BurnWithFromMintTokenPool.abi.Events["RemotePoolSet"].ID: - return _BurnWithFromMintTokenPool.ParseRemotePoolSet(log) + case _BurnWithFromMintTokenPool.abi.Events["RemotePoolAdded"].ID: + return _BurnWithFromMintTokenPool.ParseRemotePoolAdded(log) + case _BurnWithFromMintTokenPool.abi.Events["RemotePoolRemoved"].ID: + return _BurnWithFromMintTokenPool.ParseRemotePoolRemoved(log) case _BurnWithFromMintTokenPool.abi.Events["RouterUpdated"].ID: return _BurnWithFromMintTokenPool.ParseRouterUpdated(log) case _BurnWithFromMintTokenPool.abi.Events["TokensConsumed"].ID: @@ -2649,12 +2952,20 @@ func (BurnWithFromMintTokenPoolOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (BurnWithFromMintTokenPoolRateLimitAdminSet) Topic() common.Hash { + return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174") +} + func (BurnWithFromMintTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (BurnWithFromMintTokenPoolRemotePoolSet) Topic() common.Hash { - return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +func (BurnWithFromMintTokenPoolRemotePoolAdded) Topic() common.Hash { + return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") +} + +func (BurnWithFromMintTokenPoolRemotePoolRemoved) Topic() common.Hash { + return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") } func (BurnWithFromMintTokenPoolRouterUpdated) Topic() common.Hash { @@ -2680,7 +2991,7 @@ type BurnWithFromMintTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) + GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2692,6 +3003,10 @@ type BurnWithFromMintTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) + GetTokenDecimals(opts *bind.CallOpts) (uint8, error) + + IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) + IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -2704,20 +3019,22 @@ type BurnWithFromMintTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) - SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -2788,17 +3105,29 @@ type BurnWithFromMintTokenPoolInterface interface { ParseOwnershipTransferred(log types.Log) (*BurnWithFromMintTokenPoolOwnershipTransferred, error) + FilterRateLimitAdminSet(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolRateLimitAdminSetIterator, error) + + WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRateLimitAdminSet) (event.Subscription, error) + + ParseRateLimitAdminSet(log types.Log) (*BurnWithFromMintTokenPoolRateLimitAdminSet, error) + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*BurnWithFromMintTokenPoolReleasedIterator, error) WatchReleased(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) ParseReleased(log types.Log) (*BurnWithFromMintTokenPoolReleased, error) - FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolSetIterator, error) + FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolAddedIterator, error) + + WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolAdded(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolAdded, error) + + FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*BurnWithFromMintTokenPoolRemotePoolRemovedIterator, error) - WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *BurnWithFromMintTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolSet(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolSet, error) + ParseRemotePoolRemoved(log types.Log) (*BurnWithFromMintTokenPoolRemotePoolRemoved, error) FilterRouterUpdated(opts *bind.FilterOpts) (*BurnWithFromMintTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go index 275f9c7a38..32edf6ef6c 100644 --- a/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go +++ b/core/gethwrappers/ccip/generated/lock_release_token_pool/lock_release_token_pool.go @@ -74,23 +74,22 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - Allowed bool - RemotePoolAddress []byte + RemotePoolAddresses [][]byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var LockReleaseTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620049ae380380620049ae833981016040819052620000359162000565565b848484833380600081620000905760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c357620000c3816200017e565b5050506001600160a01b0384161580620000e457506001600160a01b038116155b80620000f757506001600160a01b038216155b1562000116576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c052620001695760408051600081526020810190915262000169908462000229565b5050505090151560e05250620006d692505050565b336001600160a01b03821603620001d85760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000087565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c0516200024a576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620002d55760008382815181106200026e576200026e62000688565b602090810291909101015190506200028860028262000386565b15620002cb576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b506001016200024d565b5060005b815181101562000381576000828281518110620002fa57620002fa62000688565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000326575062000378565b62000333600282620003a6565b1562000376576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620002d9565b505050565b60006200039d836001600160a01b038416620003bd565b90505b92915050565b60006200039d836001600160a01b038416620004c1565b60008181526001830160205260408120548015620004b6576000620003e46001836200069e565b8554909150600090620003fa906001906200069e565b9050808214620004665760008660000182815481106200041e576200041e62000688565b906000526020600020015490508087600001848154811062000444576200044462000688565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200047a576200047a620006c0565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003a0565b6000915050620003a0565b60008181526001830160205260408120546200050a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003a0565b506000620003a0565b6001600160a01b03811681146200052957600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b80516200054f8162000513565b919050565b805180151581146200054f57600080fd5b600080600080600060a086880312156200057e57600080fd5b85516200058b8162000513565b602087810151919650906001600160401b0380821115620005ab57600080fd5b818901915089601f830112620005c057600080fd5b815181811115620005d557620005d56200052c565b8060051b604051601f19603f83011681018181108582111715620005fd57620005fd6200052c565b60405291825284820192508381018501918c8311156200061c57600080fd5b938501935b828510156200064557620006358562000542565b8452938501939285019262000621565b8099505050505050506200065c6040870162000542565b92506200066c6060870162000554565b91506200067c6080870162000542565b90509295509295909350565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003a057634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e05161423c62000772600039600081816104ef015261174201526000818161059c01528181611cde015261278301526000818161057601528181611b0f0152611f94015260008181610290015281816102e50152818161077a0152818161084c015281816108ed0152818161180401528181611a2f01528181611eb401528181612719015261296e015261423c6000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c80638da5cb5b1161010f578063c4bffe2b116100a2578063dc0bd97111610071578063dc0bd97114610574578063e0351e131461059a578063eb521a4c146105c0578063f2fde38b146105d357600080fd5b8063c4bffe2b14610526578063c75eea9c1461053b578063cf7401f31461054e578063db6327dc1461056157600080fd5b8063b0f479a1116100de578063b0f479a1146104bc578063b7946580146104da578063bb98546b146104ed578063c0d786551461051357600080fd5b80638da5cb5b146103fa5780639a4575b914610418578063a7cd63b714610438578063af58d59f1461044d57600080fd5b806354c8a4f31161018757806378a010b21161015657806378a010b2146103b957806379ba5097146103cc5780637d54534e146103d45780638926f54f146103e757600080fd5b806354c8a4f31461036257806366320087146103755780636cfd1553146103885780636d3d1a581461039b57600080fd5b806321df0da7116101c357806321df0da71461028e578063240028e8146102d55780633907753714610322578063432a6ba31461034457600080fd5b806301ffc9a7146101f55780630a2fd4931461021d5780630a861f2a1461023d578063181f5a7714610252575b600080fd5b610208610203366004613318565b6105e6565b60405190151581526020015b60405180910390f35b61023061022b366004613377565b610642565b6040516102149190613400565b61025061024b366004613413565b6106f2565b005b6102306040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b6102086102e3366004613459565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b610335610330366004613476565b6108a3565b60405190518152602001610214565b60095473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102506103703660046134fe565b6109a9565b61025061038336600461356a565b610a24565b610250610396366004613459565b610b00565b60085473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102506103c7366004613596565b610b4f565b610250610cbe565b6102506103e2366004613459565b610dbb565b6102086103f5366004613377565b610e0a565b60005473ffffffffffffffffffffffffffffffffffffffff166102b0565b61042b610426366004613619565b610e21565b6040516102149190613654565b610440610ebb565b60405161021491906136b4565b61046061045b366004613377565b610ecc565b604051610214919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102b0565b6102306104e8366004613377565b610fa1565b7f0000000000000000000000000000000000000000000000000000000000000000610208565b610250610521366004613459565b610fcc565b61052e6110a7565b604051610214919061370e565b610460610549366004613377565b61115f565b61025061055c366004613876565b611231565b61025061056f3660046138bb565b6112ba565b7f00000000000000000000000000000000000000000000000000000000000000006102b0565b7f0000000000000000000000000000000000000000000000000000000000000000610208565b6102506105ce366004613413565b611740565b6102506105e1366004613459565b61185c565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d4056600000000000000000000000000000000000000000000000000000000148061063c575061063c82611870565b92915050565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061066d906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610699906138fd565b80156106e65780601f106106bb576101008083540402835291602001916106e6565b820191906000526020600020905b8154815290600101906020018083116106c957829003601f168201915b50505050509050919050565b60095473ffffffffffffffffffffffffffffffffffffffff16331461074a576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fa9190613950565b1015610832576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611954565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108c36108be83613a14565b611a28565b6109186108d66060840160408501613459565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906060850135611954565b6109286060830160408401613459565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52846060013560405161098a91815260200190565b60405180910390a3506040805160208101909152606090910135815290565b6109b1611c59565b610a1e84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611cdc92505050565b50505050565b610a2c611c59565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610a9457600080fd5b505af1158015610aa8573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610af491815260200190565b60405180910390a25050565b610b08611c59565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b610b57611c59565b610b6083610e0a565b610ba2576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610741565b67ffffffffffffffff831660009081526007602052604081206004018054610bc9906138fd565b80601f0160208091040260200160405190810160405280929190818152602001828054610bf5906138fd565b8015610c425780601f10610c1757610100808354040283529160200191610c42565b820191906000526020600020905b815481529060010190602001808311610c2557829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610c71838583613b59565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610cb093929190613c74565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d3f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610741565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610dc3611c59565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600061063c600567ffffffffffffffff8416611e92565b6040805180820190915260608082526020820152610e46610e4183613cd8565b611ead565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610ea08460200160208101906104e89190613377565b81526040805160208181019092526000815291015292915050565b6060610ec76002612077565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600390910154808416606083015291909104909116608082015261063c90612084565b67ffffffffffffffff8116600090815260076020526040902060050180546060919061066d906138fd565b610fd4611c59565b73ffffffffffffffffffffffffffffffffffffffff8116611021576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006110b56005612077565b90506000815167ffffffffffffffff8111156110d3576110d3613750565b6040519080825280602002602001820160405280156110fc578160200160208202803683370190505b50905060005b82518110156111585782818151811061111d5761111d613d7a565b602002602001015182828151811061113757611137613d7a565b67ffffffffffffffff90921660209283029190910190910152600101611102565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff16151594820194909452600190910154808416606083015291909104909116608082015261063c90612084565b60085473ffffffffffffffffffffffffffffffffffffffff163314801590611271575060005473ffffffffffffffffffffffffffffffffffffffff163314155b156112aa576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b6112b5838383612136565b505050565b6112c2611c59565b60005b818110156112b55760008383838181106112e1576112e1613d7a565b90506020028101906112f39190613da9565b6112fc90613de7565b90506113118160800151826020015115612220565b6113248160a00151826020015115612220565b8060200151156116205780516113469060059067ffffffffffffffff16612359565b61138b5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b60408101515115806113a05750606081015151155b156113d7576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c179091169615150295909517909855908101519401519381169316909102919091176003820155915190919060048201906115b89082613e9b565b50606082015160058201906115cd9082613e9b565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c295506116139493929190613fb5565b60405180910390a1611737565b80516116389060059067ffffffffffffffff16612365565b61167d5780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610741565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906116e660048301826132ca565b6116f46005830160006132ca565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b506001016112c5565b7f0000000000000000000000000000000000000000000000000000000000000000611797576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60095473ffffffffffffffffffffffffffffffffffffffff1633146117ea576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b61182c73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612371565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611864611c59565b61186d816123cf565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061190357507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061063c57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112b59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526124c4565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611abd5760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610741565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b8f919061404e565b15611bc6576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bd381602001516125d0565b6000611be28260200151610642565b9050805160001480611c06575080805190602001208260a001518051906020012014155b15611c43578160a001516040517f24eb47e50000000000000000000000000000000000000000000000000000000081526004016107419190613400565b611c55826020015183606001516126f6565b5050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611cda576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610741565b565b7f0000000000000000000000000000000000000000000000000000000000000000611d33576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015611dc9576000838281518110611d5357611d53613d7a565b60200260200101519050611d7181600261273d90919063ffffffff16565b15611dc05760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611d36565b5060005b81518110156112b5576000828281518110611dea57611dea613d7a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611e2e5750611e8a565b611e3960028261275f565b15611e885760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101611dcd565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611f425760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610741565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611ff0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612014919061404e565b1561204b576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120588160400151612781565b6120658160200151612800565b61186d8160200151826060015161294e565b60606000611ea683612992565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261211282606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426120f6919061409a565b85608001516fffffffffffffffffffffffffffffffff166129ed565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61213f83610e0a565b612181576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610741565b61218c826000612220565b67ffffffffffffffff831660009081526007602052604090206121af9083612a17565b6121ba816000612220565b67ffffffffffffffff831660009081526007602052604090206121e09060020182612a17565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b838383604051612213939291906140ad565b60405180910390a1505050565b8151156122e75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612276575060408201516fffffffffffffffffffffffffffffffff16155b156122af57816040517f8020d1240000000000000000000000000000000000000000000000000000000081526004016107419190614130565b8015611c55576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612320575060208201516fffffffffffffffffffffffffffffffff1615155b15611c5557816040517fd68af9cc0000000000000000000000000000000000000000000000000000000081526004016107419190614130565b6000611ea68383612bb9565b6000611ea68383612c08565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610a1e9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016119a6565b3373ffffffffffffffffffffffffffffffffffffffff82160361244e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610741565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612526826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612cfb9092919063ffffffff16565b8051909150156112b55780806020019051810190612544919061404e565b6112b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610741565b6125d981610e0a565b61261b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610741565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa15801561269a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126be919061404e565b61186d576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b67ffffffffffffffff82166000908152600760205260409020611c5590600201827f0000000000000000000000000000000000000000000000000000000000000000612d0a565b6000611ea68373ffffffffffffffffffffffffffffffffffffffff8416612c08565b6000611ea68373ffffffffffffffffffffffffffffffffffffffff8416612bb9565b7f00000000000000000000000000000000000000000000000000000000000000001561186d576127b260028261308d565b61186d576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610741565b61280981610e0a565b61284b576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610741565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156128c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128e8919061416c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461186d576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610741565b67ffffffffffffffff82166000908152600760205260409020611c5590827f0000000000000000000000000000000000000000000000000000000000000000612d0a565b6060816000018054806020026020016040519081016040528092919081815260200182805480156106e657602002820191906000526020600020905b8154815260200190600101908083116129ce5750505050509050919050565b6000612a0c856129fd8486614189565b612a0790876141a0565b6130bc565b90505b949350505050565b8154600090612a4090700100000000000000000000000000000000900463ffffffff164261409a565b90508015612ae25760018301548354612a88916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166129ed565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612b08916fffffffffffffffffffffffffffffffff90811691166130bc565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c1990612213908490614130565b6000818152600183016020526040812054612c005750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561063c565b50600061063c565b60008181526001830160205260408120548015612cf1576000612c2c60018361409a565b8554909150600090612c409060019061409a565b9050808214612ca5576000866000018281548110612c6057612c60613d7a565b9060005260206000200154905080876000018481548110612c8357612c83613d7a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612cb657612cb66141b3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061063c565b600091505061063c565b6060612a0f84846000856130d2565b825474010000000000000000000000000000000000000000900460ff161580612d31575081155b15612d3b57505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612d8190700100000000000000000000000000000000900463ffffffff164261409a565b90508015612e415781831115612dc3576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612dfd9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166129ed565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612ef85773ffffffffffffffffffffffffffffffffffffffff8416612ea0576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610741565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610741565b8483101561300b5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290612f3c908261409a565b612f46878a61409a565b612f5091906141a0565b612f5a91906141e2565b905073ffffffffffffffffffffffffffffffffffffffff8616612fb3576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610741565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610741565b613015858461409a565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515611ea6565b60008183106130cb5781611ea6565b5090919050565b606082471015613164576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610741565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161318d919061421d565b60006040518083038185875af1925050503d80600081146131ca576040519150601f19603f3d011682016040523d82523d6000602084013e6131cf565b606091505b50915091506131e0878383876131eb565b979650505050505050565b6060831561328157825160000361327a5773ffffffffffffffffffffffffffffffffffffffff85163b61327a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610741565b5081612a0f565b612a0f83838151156132965781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107419190613400565b5080546132d6906138fd565b6000825580601f106132e6575050565b601f01602090049060005260206000209081019061186d91905b808211156133145760008155600101613300565b5090565b60006020828403121561332a57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611ea657600080fd5b803567ffffffffffffffff8116811461337257600080fd5b919050565b60006020828403121561338957600080fd5b611ea68261335a565b60005b838110156133ad578181015183820152602001613395565b50506000910152565b600081518084526133ce816020860160208601613392565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611ea660208301846133b6565b60006020828403121561342557600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461186d57600080fd5b80356133728161342c565b60006020828403121561346b57600080fd5b8135611ea68161342c565b60006020828403121561348857600080fd5b813567ffffffffffffffff81111561349f57600080fd5b82016101008185031215611ea657600080fd5b60008083601f8401126134c457600080fd5b50813567ffffffffffffffff8111156134dc57600080fd5b6020830191508360208260051b85010111156134f757600080fd5b9250929050565b6000806000806040858703121561351457600080fd5b843567ffffffffffffffff8082111561352c57600080fd5b613538888389016134b2565b9096509450602087013591508082111561355157600080fd5b5061355e878288016134b2565b95989497509550505050565b6000806040838503121561357d57600080fd5b82356135888161342c565b946020939093013593505050565b6000806000604084860312156135ab57600080fd5b6135b48461335a565b9250602084013567ffffffffffffffff808211156135d157600080fd5b818601915086601f8301126135e557600080fd5b8135818111156135f457600080fd5b87602082850101111561360657600080fd5b6020830194508093505050509250925092565b60006020828403121561362b57600080fd5b813567ffffffffffffffff81111561364257600080fd5b820160a08185031215611ea657600080fd5b60208152600082516040602084015261367060608401826133b6565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526136ab82826133b6565b95945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561370257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016136d0565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561370257835167ffffffffffffffff168352928401929184019160010161372a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156137a3576137a3613750565b60405290565b60405160c0810167ffffffffffffffff811182821017156137a3576137a3613750565b801515811461186d57600080fd5b8035613372816137cc565b80356fffffffffffffffffffffffffffffffff8116811461337257600080fd5b60006060828403121561381757600080fd5b6040516060810181811067ffffffffffffffff8211171561383a5761383a613750565b604052905080823561384b816137cc565b8152613859602084016137e5565b602082015261386a604084016137e5565b60408201525092915050565b600080600060e0848603121561388b57600080fd5b6138948461335a565b92506138a38560208601613805565b91506138b28560808601613805565b90509250925092565b600080602083850312156138ce57600080fd5b823567ffffffffffffffff8111156138e557600080fd5b6138f1858286016134b2565b90969095509350505050565b600181811c9082168061391157607f821691505b60208210810361394a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561396257600080fd5b5051919050565b600082601f83011261397a57600080fd5b813567ffffffffffffffff8082111561399557613995613750565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156139db576139db613750565b816040528381528660208588010111156139f457600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101008236031215613a2757600080fd5b613a2f61377f565b823567ffffffffffffffff80821115613a4757600080fd5b613a5336838701613969565b8352613a616020860161335a565b6020840152613a726040860161344e565b604084015260608501356060840152613a8d6080860161344e565b608084015260a0850135915080821115613aa657600080fd5b613ab236838701613969565b60a084015260c0850135915080821115613acb57600080fd5b613ad736838701613969565b60c084015260e0850135915080821115613af057600080fd5b50613afd36828601613969565b60e08301525092915050565b601f8211156112b5576000816000526020600020601f850160051c81016020861015613b325750805b601f850160051c820191505b81811015613b5157828155600101613b3e565b505050505050565b67ffffffffffffffff831115613b7157613b71613750565b613b8583613b7f83546138fd565b83613b09565b6000601f841160018114613bd75760008515613ba15750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613c6d565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613c265786850135825560209485019460019092019101613c06565b5086821015613c61577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b604081526000613c8760408301866133b6565b82810360208401528381528385602083013760006020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116820101915050949350505050565b600060a08236031215613cea57600080fd5b60405160a0810167ffffffffffffffff8282108183111715613d0e57613d0e613750565b816040528435915080821115613d2357600080fd5b50613d3036828601613969565b825250613d3f6020840161335a565b60208201526040830135613d528161342c565b6040820152606083810135908201526080830135613d6f8161342c565b608082015292915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613ddd57600080fd5b9190910192915050565b60006101408236031215613dfa57600080fd5b613e026137a9565b613e0b8361335a565b8152613e19602084016137da565b6020820152604083013567ffffffffffffffff80821115613e3957600080fd5b613e4536838701613969565b60408401526060850135915080821115613e5e57600080fd5b50613e6b36828601613969565b606083015250613e7e3660808501613805565b6080820152613e903660e08501613805565b60a082015292915050565b815167ffffffffffffffff811115613eb557613eb5613750565b613ec981613ec384546138fd565b84613b09565b602080601f831160018114613f1c5760008415613ee65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b51565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613f6957888601518255948401946001909101908401613f4a565b5085821015613fa557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff87168352806020840152613fd9818401876133b6565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506140179050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526136ab565b60006020828403121561406057600080fd5b8151611ea6816137cc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561063c5761063c61406b565b67ffffffffffffffff8416815260e081016140f960208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612a0f565b6060810161063c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561417e57600080fd5b8151611ea68161342c565b808202811582820484141761063c5761063c61406b565b8082018082111561063c5761063c61406b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082614218577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008251613ddd81846020870161339256fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"localTokenDecimals\",\"type\":\"uint8\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"acceptLiquidity\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLiquidity\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LiquidityNotAccepted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"provider\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LiquidityTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"canAcceptLiquidity\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRebalancer\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"provideLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rebalancer\",\"type\":\"address\"}],\"name\":\"setRebalancer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLiquidity\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b506040516200511f3803806200511f8339810160408190526200003591620005bb565b8585858584336000816200005c57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200008f576200008f81620001f3565b50506001600160a01b0385161580620000af57506001600160a01b038116155b80620000c257506001600160a01b038216155b15620000e1576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000151575060408051601f3d908101601f191682019092526200014e91810190620006ee565b60015b1562000191578060ff168560ff16146200018f576040516332ad3e0760e11b815260ff80871660048301528216602482015260440160405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001db57604080516000815260208101909152620001db90846200026d565b5050505091151561010052506200075a945050505050565b336001600160a01b038216036200021d57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200028e576040516335f4a7b360e01b815260040160405180910390fd5b60005b825181101562000319576000838281518110620002b257620002b26200070c565b60209081029190910101519050620002cc600282620003ca565b156200030f576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000291565b5060005b8151811015620003c55760008282815181106200033e576200033e6200070c565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200036a5750620003bc565b62000377600282620003ea565b15620003ba576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b6001016200031d565b505050565b6000620003e1836001600160a01b03841662000401565b90505b92915050565b6000620003e1836001600160a01b03841662000505565b60008181526001830160205260408120548015620004fa5760006200042860018362000722565b85549091506000906200043e9060019062000722565b9050808214620004aa5760008660000182815481106200046257620004626200070c565b90600052602060002001549050808760000184815481106200048857620004886200070c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620004be57620004be62000744565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050620003e4565b6000915050620003e4565b60008181526001830160205260408120546200054e57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620003e4565b506000620003e4565b6001600160a01b03811681146200056d57600080fd5b50565b805160ff811681146200058257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b8051620005828162000557565b805180151581146200058257600080fd5b60008060008060008060c08789031215620005d557600080fd5b8651620005e28162000557565b95506020620005f388820162000570565b60408901519096506001600160401b03808211156200061157600080fd5b818a0191508a601f8301126200062657600080fd5b8151818111156200063b576200063b62000587565b8060051b604051601f19603f8301168101818110858211171562000663576200066362000587565b60405291825284820192508381018501918d8311156200068257600080fd5b938501935b82851015620006ab576200069b856200059d565b8452938501939285019262000687565b809950505050505050620006c2606088016200059d565b9250620006d260808801620005aa565b9150620006e260a088016200059d565b90509295509295509295565b6000602082840312156200070157600080fd5b620003e18262000570565b634e487b7160e01b600052603260045260246000fd5b81810381811115620003e457634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c05160e051610100516148f46200082b600039600081816105a40152611ac601526000818161063e015281816123180152612e3101526000818161061801528181611e35015261260401526000818161036701528181610e6b01528181611fde01528181612098015281816120cc015281816120ff01528181612164015281816121bd015261225f0152600081816102ce015281816103230152818161077f015281816108510152818161094501528181611b8801528181612dc7015261301c01526148f46000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c80638da5cb5b11610145578063c0d78655116100bd578063dc0bd9711161008c578063e8a1da1711610071578063e8a1da1714610662578063eb521a4c14610675578063f2fde38b1461068857600080fd5b8063dc0bd97114610616578063e0351e131461063c57600080fd5b8063c0d78655146105c8578063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f31461060357600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610571578063b79465801461058f578063bb98546b146105a257600080fd5b8063acfecf91146104ef578063af58d59f1461050257600080fd5b80638da5cb5b1461047c5780639a4575b91461049a578063a42a7b8b146104ba578063a7cd63b7146104da57600080fd5b80634c5ef0ed116101d85780636cfd1553116101a757806379ba50971161018c57806379ba50971461044e5780637d54534e146104565780638926f54f1461046957600080fd5b80636cfd15531461041d5780636d3d1a581461043057600080fd5b80634c5ef0ed146103d157806354c8a4f3146103e457806362ddd3c4146103f7578063663200871461040a57600080fd5b8063240028e811610214578063240028e81461031357806324f65ee7146103605780633907753714610391578063432a6ba3146103b357600080fd5b806301ffc9a7146102465780630a861f2a1461026e578063181f5a771461028357806321df0da7146102cc575b600080fd5b6102596102543660046139e3565b61069b565b60405190151581526020015b60405180910390f35b61028161027c366004613a25565b6106f7565b005b6102bf6040518060400160405280601a81526020017f4c6f636b52656c65617365546f6b656e506f6f6c20312e352e3100000000000081525081565b6040516102659190613aac565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610265565b610259610321366004613ae1565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610265565b6103a461039f366004613afe565b6108a8565b60405190518152602001610265565b600a5473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102596103df366004613b57565b6109f6565b6102816103f2366004613c26565b610a40565b610281610405366004613b57565b610abb565b610281610418366004613c92565b610b53565b61028161042b366004613ae1565b610c2f565b60095473ffffffffffffffffffffffffffffffffffffffff166102ee565b610281610c7e565b610281610464366004613ae1565b610d4c565b610259610477366004613cbe565b610dcd565b60015473ffffffffffffffffffffffffffffffffffffffff166102ee565b6104ad6104a8366004613cd9565b610de4565b6040516102659190613d14565b6104cd6104c8366004613cbe565b610eb0565b6040516102659190613d6b565b6104e261101b565b6040516102659190613ded565b6102816104fd366004613b57565b61102c565b610515610510366004613cbe565b611144565b604051610265919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ee565b6102bf61059d366004613cbe565b611219565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b6102816105d6366004613ae1565b6112c9565b6105e36113a4565b6040516102659190613e47565b6105156105fe366004613cbe565b61145c565b610281610611366004613fcf565b61152e565b7f00000000000000000000000000000000000000000000000000000000000000006102ee565b7f0000000000000000000000000000000000000000000000000000000000000000610259565b610281610670366004613c26565b6115b2565b610281610683366004613a25565b611ac4565b610281610696366004613ae1565b611be0565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fe1d405660000000000000000000000000000000000000000000000000000000014806106f157506106f182611bf4565b92915050565b600a5473ffffffffffffffffffffffffffffffffffffffff16331461074f576040517f8e4a23d60000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156107db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ff9190614014565b1015610837576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087873ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611cd8565b604051819033907fc2c3f06e49b9f15e7b4af9055e183b0d73362e033ad82a07dec9bf984017171990600090a350565b6040805160208101909152600081526108c082611dac565b600061091960608401356109146108da60c087018761402d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611fd092505050565b612094565b905061096c61092e6060850160408601613ae1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169083611cd8565b61097c6060840160408501613ae1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52836040516109da91815260200190565b60405180910390a3604080516020810190915290815292915050565b6000610a388383604051610a0b929190614092565b604080519182900390912067ffffffffffffffff87166000908152600760205291909120600501906122a8565b949350505050565b610a486122c3565b610ab58484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061231692505050565b50505050565b610ac36122c3565b610acc83610dcd565b610b0e576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b610b4e8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124cc92505050565b505050565b610b5b6122c3565b6040517f0a861f2a0000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff831690630a861f2a90602401600060405180830381600087803b158015610bc357600080fd5b505af1158015610bd7573d6000803e3d6000fd5b505050508173ffffffffffffffffffffffffffffffffffffffff167f6fa7abcf1345d1d478e5ea0da6b5f26a90eadb0546ef15ed3833944fbfd1db6282604051610c2391815260200190565b60405180910390a25050565b610c376122c3565b600a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610ccf576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610d546122c3565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006106f1600567ffffffffffffffff84166122a8565b6040805180820190915260608082526020820152610e01826125c6565b6040516060830135815233907f9f1ec8c880f76798e7b793325d625e9b60e4082a553c98f42b6cda368dd600089060200160405180910390a26040518060400160405280610e5b84602001602081019061059d9190613cbe565b8152602001610ea86040805160ff7f000000000000000000000000000000000000000000000000000000000000000016602082015260609101604051602081830303815290604052905090565b905292915050565b67ffffffffffffffff8116600090815260076020526040812060609190610ed990600501612752565b90506000815167ffffffffffffffff811115610ef757610ef7613e89565b604051908082528060200260200182016040528015610f2a57816020015b6060815260200190600190039081610f155790505b50905060005b82518110156110135760086000848381518110610f4f57610f4f6140a2565b602002602001015181526020019081526020016000208054610f70906140d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9c906140d1565b8015610fe95780601f10610fbe57610100808354040283529160200191610fe9565b820191906000526020600020905b815481529060010190602001808311610fcc57829003601f168201915b5050505050828281518110611000576110006140a2565b6020908102919091010152600101610f30565b509392505050565b60606110276002612752565b905090565b6110346122c3565b61103d83610dcd565b61107f576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b6110bf8282604051611092929190614092565b604080519182900390912067ffffffffffffffff861660009081526007602052919091206005019061275f565b6110fb578282826040517f74f23c7c0000000000000000000000000000000000000000000000000000000081526004016107469392919061416d565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d768383604051611137929190614191565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526106f19061276b565b67ffffffffffffffff81166000908152600760205260409020600401805460609190611244906140d1565b80601f0160208091040260200160405190810160405280929190818152602001828054611270906140d1565b80156112bd5780601f10611292576101008083540402835291602001916112bd565b820191906000526020600020905b8154815290600101906020018083116112a057829003601f168201915b50505050509050919050565b6112d16122c3565b73ffffffffffffffffffffffffffffffffffffffff811661131e576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f1684910160405180910390a15050565b606060006113b26005612752565b90506000815167ffffffffffffffff8111156113d0576113d0613e89565b6040519080825280602002602001820160405280156113f9578160200160208202803683370190505b50905060005b82518110156114555782818151811061141a5761141a6140a2565b6020026020010151828281518110611434576114346140a2565b67ffffffffffffffff909216602092830291909101909101526001016113ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526106f19061276b565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061156e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156115a7576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b610b4e83838361281d565b6115ba6122c3565b60005b838110156117a75760008585838181106115d9576115d96140a2565b90506020020160208101906115ee9190613cbe565b9050611605600567ffffffffffffffff831661275f565b611647576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b67ffffffffffffffff8116600090815260076020526040812061166c90600501612752565b905060005b81518110156116d8576116cf82828151811061168f5761168f6140a2565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161275f90919063ffffffff16565b50600101611671565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff000000000000000000000000000000000000000000908116825560018201839055600282018054909116905560038101829055906117416004830182613976565b600582016000818161175382826139b0565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611795915050565b60405180910390a150506001016115bd565b5060005b81811015611abd5760008383838181106117c7576117c76140a2565b90506020028101906117d991906141a5565b6117e290614271565b90506117f381606001516000612907565b61180281608001516000612907565b806040015151600003611841576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516118599060059067ffffffffffffffff16612a44565b61189e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610746565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611a2190826143e8565b5060005b826020015151811015611a6557611a5d836000015184602001518381518110611a5057611a506140a2565b60200260200101516124cc565b600101611a25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611aab9493929190614502565b60405180910390a150506001016117ab565b5050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611b1b576040517fe93f8fa400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600a5473ffffffffffffffffffffffffffffffffffffffff163314611b6e576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b611bb073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612a50565b604051819033907fc17cea59c2955cb181b03393209566960365771dbba9dc3d510180e7cb31208890600090a350565b611be86122c3565b611bf181612aae565b50565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf000000000000000000000000000000000000000000000000000000001480611c8757507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806106f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052610b4e9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612b72565b611dbf61032160a0830160808401613ae1565b611e1e57611dd360a0820160808301613ae1565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610746565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611e6a6040840160208501613cbe565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611edb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eff919061459b565b15611f36576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611f4e611f496040830160208401613cbe565b612c7e565b611f6e611f616040830160208401613cbe565b6103df60a084018461402d565b611fb357611f7f60a082018261402d565b6040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610746929190614191565b611bf1611fc66040830160208401613cbe565b8260600135612da4565b6000815160000361200257507f0000000000000000000000000000000000000000000000000000000000000000919050565b815160201461203f57816040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b6000828060200190518101906120559190614014565b905060ff8111156106f157826040517f953576f70000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b60007f000000000000000000000000000000000000000000000000000000000000000060ff168260ff16036120ca5750816106f1565b7f000000000000000000000000000000000000000000000000000000000000000060ff168260ff1611156121b55760006121247f0000000000000000000000000000000000000000000000000000000000000000846145e7565b9050604d8160ff161115612198576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610746565b6121a381600a614720565b6121ad908561472f565b9150506106f1565b60006121e1837f00000000000000000000000000000000000000000000000000000000000000006145e7565b9050604d8160ff16118061222857506121fb81600a614720565b612225907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61472f565b84115b15612293576040517fa9cb113d00000000000000000000000000000000000000000000000000000000815260ff80851660048301527f000000000000000000000000000000000000000000000000000000000000000016602482015260448101859052606401610746565b61229e81600a614720565b610a38908561476a565b600081815260018301602052604081205415155b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314612314576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b7f000000000000000000000000000000000000000000000000000000000000000061236d576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561240357600083828151811061238d5761238d6140a2565b602002602001015190506123ab816002612deb90919063ffffffff16565b156123fa5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612370565b5060005b8151811015610b4e576000828281518110612424576124246140a2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361246857506124c4565b612473600282612e0d565b156124c25760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612407565b8051600003612507576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff84166000908152600790925260409091206125399060050182612a44565b6125735782826040517f393b8ad2000000000000000000000000000000000000000000000000000000008152600401610746929190614781565b600081815260086020526040902061258b83826143e8565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea836040516111379190613aac565b6125d961032160a0830160808401613ae1565b6125ed57611dd360a0820160808301613ae1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb6126396040840160208501613cbe565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156126aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126ce919061459b565b15612705576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61271d6127186060830160408401613ae1565b612e2f565b6127356127306040830160208401613cbe565b612eae565b611bf16127486040830160208401613cbe565b8260600135612ffc565b606060006122bc83613040565b60006122bc838361309b565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526127f982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426127dd91906147a4565b85608001516fffffffffffffffffffffffffffffffff1661318e565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61282683610dcd565b612868576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610746565b612873826000612907565b67ffffffffffffffff8316600090815260076020526040902061289690836131b6565b6128a1816000612907565b67ffffffffffffffff831660009081526007602052604090206128c790600201826131b6565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516128fa939291906147b7565b60405180910390a1505050565b8151156129d25781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff1610158061295d575060408201516fffffffffffffffffffffffffffffffff16155b1561299657816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610746919061483a565b80156129ce576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612a0b575060208201516fffffffffffffffffffffffffffffffff1615155b156129ce57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610746919061483a565b60006122bc8383613358565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052610ab59085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611d2a565b3373ffffffffffffffffffffffffffffffffffffffff821603612afd576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000612bd4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133a79092919063ffffffff16565b805190915015610b4e5780806020019051810190612bf2919061459b565b610b4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610746565b612c8781610dcd565b612cc9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d6c919061459b565b611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206129ce90600201827f00000000000000000000000000000000000000000000000000000000000000006133b6565b60006122bc8373ffffffffffffffffffffffffffffffffffffffff841661309b565b60006122bc8373ffffffffffffffffffffffffffffffffffffffff8416613358565b7f000000000000000000000000000000000000000000000000000000000000000015611bf157612e60600282613739565b611bf1576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610746565b612eb781610dcd565b612ef9576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610746565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612f72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f969190614876565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611bf1576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610746565b67ffffffffffffffff821660009081526007602052604090206129ce90827f00000000000000000000000000000000000000000000000000000000000000006133b6565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112bd57602002820191906000526020600020905b81548152602001906001019080831161307c5750505050509050919050565b600081815260018301602052604081205480156131845760006130bf6001836147a4565b85549091506000906130d3906001906147a4565b90508082146131385760008660000182815481106130f3576130f36140a2565b9060005260206000200154905080876000018481548110613116576131166140a2565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061314957613149614893565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506106f1565b60009150506106f1565b60006131ad8561319e848661476a565b6131a890876148c2565b613768565b95945050505050565b81546000906131df90700100000000000000000000000000000000900463ffffffff16426147a4565b905080156132815760018301548354613227916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661318e565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546132a7916fffffffffffffffffffffffffffffffff9081169116613768565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906128fa90849061483a565b600081815260018301602052604081205461339f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556106f1565b5060006106f1565b6060610a38848460008561377e565b825474010000000000000000000000000000000000000000900460ff1615806133dd575081155b156133e757505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061342d90700100000000000000000000000000000000900463ffffffff16426147a4565b905080156134ed578183111561346f576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546134a99083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661318e565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156135a45773ffffffffffffffffffffffffffffffffffffffff841661354c576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610746565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610746565b848310156136b75760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906135e890826147a4565b6135f2878a6147a4565b6135fc91906148c2565b613606919061472f565b905073ffffffffffffffffffffffffffffffffffffffff861661365f576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610746565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610746565b6136c185846147a4565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260018301602052604081205415156122bc565b600081831061377757816122bc565b5090919050565b606082471015613810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610746565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161383991906148d5565b60006040518083038185875af1925050503d8060008114613876576040519150601f19603f3d011682016040523d82523d6000602084013e61387b565b606091505b509150915061388c87838387613897565b979650505050505050565b6060831561392d5782516000036139265773ffffffffffffffffffffffffffffffffffffffff85163b613926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610746565b5081610a38565b610a3883838151156139425781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107469190613aac565b508054613982906140d1565b6000825580601f10613992575050565b601f016020900490600052602060002090810190611bf191906139ca565b5080546000825590600052602060002090810190611bf191905b5b808211156139df57600081556001016139cb565b5090565b6000602082840312156139f557600080fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146122bc57600080fd5b600060208284031215613a3757600080fd5b5035919050565b60005b83811015613a59578181015183820152602001613a41565b50506000910152565b60008151808452613a7a816020860160208601613a3e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006122bc6020830184613a62565b73ffffffffffffffffffffffffffffffffffffffff81168114611bf157600080fd5b600060208284031215613af357600080fd5b81356122bc81613abf565b600060208284031215613b1057600080fd5b813567ffffffffffffffff811115613b2757600080fd5b820161010081850312156122bc57600080fd5b803567ffffffffffffffff81168114613b5257600080fd5b919050565b600080600060408486031215613b6c57600080fd5b613b7584613b3a565b9250602084013567ffffffffffffffff80821115613b9257600080fd5b818601915086601f830112613ba657600080fd5b813581811115613bb557600080fd5b876020828501011115613bc757600080fd5b6020830194508093505050509250925092565b60008083601f840112613bec57600080fd5b50813567ffffffffffffffff811115613c0457600080fd5b6020830191508360208260051b8501011115613c1f57600080fd5b9250929050565b60008060008060408587031215613c3c57600080fd5b843567ffffffffffffffff80821115613c5457600080fd5b613c6088838901613bda565b90965094506020870135915080821115613c7957600080fd5b50613c8687828801613bda565b95989497509550505050565b60008060408385031215613ca557600080fd5b8235613cb081613abf565b946020939093013593505050565b600060208284031215613cd057600080fd5b6122bc82613b3a565b600060208284031215613ceb57600080fd5b813567ffffffffffffffff811115613d0257600080fd5b820160a081850312156122bc57600080fd5b602081526000825160406020840152613d306060840182613a62565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526131ad8282613a62565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613de0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613dce858351613a62565b94509285019290850190600101613d94565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613e3b57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101613e09565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613e3b57835167ffffffffffffffff1683529284019291840191600101613e63565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715613edb57613edb613e89565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613f2857613f28613e89565b604052919050565b8015158114611bf157600080fd5b80356fffffffffffffffffffffffffffffffff81168114613b5257600080fd5b600060608284031215613f7057600080fd5b6040516060810181811067ffffffffffffffff82111715613f9357613f93613e89565b6040529050808235613fa481613f30565b8152613fb260208401613f3e565b6020820152613fc360408401613f3e565b60408201525092915050565b600080600060e08486031215613fe457600080fd5b613fed84613b3a565b9250613ffc8560208601613f5e565b915061400b8560808601613f5e565b90509250925092565b60006020828403121561402657600080fd5b5051919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261406257600080fd5b83018035915067ffffffffffffffff82111561407d57600080fd5b602001915036819003821315613c1f57600080fd5b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806140e557607f821691505b60208210810361411e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b67ffffffffffffffff841681526040602082015260006131ad604083018486614124565b602081526000610a38602083018486614124565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee18336030181126141d957600080fd5b9190910192915050565b600082601f8301126141f457600080fd5b813567ffffffffffffffff81111561420e5761420e613e89565b61423f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613ee1565b81815284602083860101111561425457600080fd5b816020850160208301376000918101602001919091529392505050565b6000610120823603121561428457600080fd5b61428c613eb8565b61429583613b3a565b815260208084013567ffffffffffffffff808211156142b357600080fd5b9085019036601f8301126142c657600080fd5b8135818111156142d8576142d8613e89565b8060051b6142e7858201613ee1565b918252838101850191858101903684111561430157600080fd5b86860192505b8383101561433d5782358581111561431f5760008081fd5b61432d3689838a01016141e3565b8352509186019190860190614307565b808789015250505050604086013592508083111561435a57600080fd5b5050614368368286016141e3565b60408301525061437b3660608501613f5e565b606082015261438d3660c08501613f5e565b608082015292915050565b601f821115610b4e576000816000526020600020601f850160051c810160208610156143c15750805b601f850160051c820191505b818110156143e0578281556001016143cd565b505050505050565b815167ffffffffffffffff81111561440257614402613e89565b6144168161441084546140d1565b84614398565b602080601f83116001811461446957600084156144335750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556143e0565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156144b657888601518255948401946001909101908401614497565b50858210156144f257878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff8716835280602084015261452681840187613a62565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506145649050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526131ad565b6000602082840312156145ad57600080fd5b81516122bc81613f30565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff82811682821603908111156106f1576106f16145b8565b600181815b8085111561465957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561463f5761463f6145b8565b8085161561464c57918102915b93841c9390800290614605565b509250929050565b600082614670575060016106f1565b8161467d575060006106f1565b8160018114614693576002811461469d576146b9565b60019150506106f1565b60ff8411156146ae576146ae6145b8565b50506001821b6106f1565b5060208310610133831016604e8410600b84101617156146dc575081810a6106f1565b6146e68383614600565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614718576147186145b8565b029392505050565b60006122bc60ff841683614661565b600082614765577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176106f1576106f16145b8565b67ffffffffffffffff83168152604060208201526000610a386040830184613a62565b818103818111156106f1576106f16145b8565b67ffffffffffffffff8416815260e0810161480360208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610a38565b606081016106f182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561488857600080fd5b81516122bc81613abf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b808201808211156106f1576106f16145b8565b600082516141d9818460208701613a3e56fea164736f6c6343000818000a", } var LockReleaseTokenPoolABI = LockReleaseTokenPoolMetaData.ABI var LockReleaseTokenPoolBin = LockReleaseTokenPoolMetaData.Bin -func DeployLockReleaseTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, allowlist []common.Address, rmnProxy common.Address, acceptLiquidity bool, router common.Address) (common.Address, *types.Transaction, *LockReleaseTokenPool, error) { +func DeployLockReleaseTokenPool(auth *bind.TransactOpts, backend bind.ContractBackend, token common.Address, localTokenDecimals uint8, allowlist []common.Address, rmnProxy common.Address, acceptLiquidity bool, router common.Address) (common.Address, *types.Transaction, *LockReleaseTokenPool, error) { parsed, err := LockReleaseTokenPoolMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -99,7 +98,7 @@ func DeployLockReleaseTokenPool(auth *bind.TransactOpts, backend bind.ContractBa return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LockReleaseTokenPoolBin), backend, token, allowlist, rmnProxy, acceptLiquidity, router) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(LockReleaseTokenPoolBin), backend, token, localTokenDecimals, allowlist, rmnProxy, acceptLiquidity, router) if err != nil { return common.Address{}, nil, nil, err } @@ -376,26 +375,26 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetRebalancer() return _LockReleaseTokenPool.Contract.GetRebalancer(&_LockReleaseTokenPool.CallOpts) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { +func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { var out []interface{} - err := _LockReleaseTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + err := _LockReleaseTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) if err != nil { - return *new([]byte), err + return *new([][]byte), err } - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) return out0, err } -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _LockReleaseTokenPool.Contract.GetRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _LockReleaseTokenPool.Contract.GetRemotePools(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _LockReleaseTokenPool.Contract.GetRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) +func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _LockReleaseTokenPool.Contract.GetRemotePools(&_LockReleaseTokenPool.CallOpts, remoteChainSelector) } func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -508,6 +507,50 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetToken() (comm return _LockReleaseTokenPool.Contract.GetToken(&_LockReleaseTokenPool.CallOpts) } +func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _LockReleaseTokenPool.contract.Call(opts, &out, "getTokenDecimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) GetTokenDecimals() (uint8, error) { + return _LockReleaseTokenPool.Contract.GetTokenDecimals(&_LockReleaseTokenPool.CallOpts) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { + return _LockReleaseTokenPool.Contract.GetTokenDecimals(&_LockReleaseTokenPool.CallOpts) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + var out []interface{} + err := _LockReleaseTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _LockReleaseTokenPool.Contract.IsRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _LockReleaseTokenPool.Contract.IsRemotePool(&_LockReleaseTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + func (_LockReleaseTokenPool *LockReleaseTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _LockReleaseTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -630,6 +673,18 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) AcceptOwners return _LockReleaseTokenPool.Contract.AcceptOwnership(&_LockReleaseTokenPool.TransactOpts) } +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.AddRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.AddRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -642,16 +697,16 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ApplyAllowLi return _LockReleaseTokenPool.Contract.ApplyAllowListUpdates(&_LockReleaseTokenPool.TransactOpts, removes, adds) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _LockReleaseTokenPool.contract.Transact(opts, "applyChainUpdates", chains) +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _LockReleaseTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, chains) +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, chains) +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.ApplyChainUpdates(&_LockReleaseTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -690,6 +745,18 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) ReleaseOrMin return _LockReleaseTokenPool.Contract.ReleaseOrMint(&_LockReleaseTokenPool.TransactOpts, releaseOrMintIn) } +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.RemoveRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _LockReleaseTokenPool.Contract.RemoveRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -726,18 +793,6 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetRebalance return _LockReleaseTokenPool.Contract.SetRebalancer(&_LockReleaseTokenPool.TransactOpts, rebalancer) } -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.SetRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _LockReleaseTokenPool.Contract.SetRemotePool(&_LockReleaseTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_LockReleaseTokenPool *LockReleaseTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _LockReleaseTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2558,6 +2613,123 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseOwnershipTransfe return event, nil } +type LockReleaseTokenPoolRateLimitAdminSetIterator struct { + Event *LockReleaseTokenPoolRateLimitAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LockReleaseTokenPoolRateLimitAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LockReleaseTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LockReleaseTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LockReleaseTokenPoolRateLimitAdminSetIterator) Error() error { + return it.fail +} + +func (it *LockReleaseTokenPoolRateLimitAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LockReleaseTokenPoolRateLimitAdminSet struct { + RateLimitAdmin common.Address + Raw types.Log +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*LockReleaseTokenPoolRateLimitAdminSetIterator, error) { + + logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return &LockReleaseTokenPoolRateLimitAdminSetIterator{contract: _LockReleaseTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRateLimitAdminSet) (event.Subscription, error) { + + logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LockReleaseTokenPoolRateLimitAdminSet) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*LockReleaseTokenPoolRateLimitAdminSet, error) { + event := new(LockReleaseTokenPoolRateLimitAdminSet) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type LockReleaseTokenPoolReleasedIterator struct { Event *LockReleaseTokenPoolReleased @@ -2695,8 +2867,136 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseReleased(log typ return event, nil } -type LockReleaseTokenPoolRemotePoolSetIterator struct { - Event *LockReleaseTokenPoolRemotePoolSet +type LockReleaseTokenPoolRemotePoolAddedIterator struct { + Event *LockReleaseTokenPoolRemotePoolAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(LockReleaseTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(LockReleaseTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Error() error { + return it.fail +} + +func (it *LockReleaseTokenPoolRemotePoolAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type LockReleaseTokenPoolRemotePoolAdded struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolAddedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &LockReleaseTokenPoolRemotePoolAddedIterator{contract: _LockReleaseTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(LockReleaseTokenPoolRemotePoolAdded) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*LockReleaseTokenPoolRemotePoolAdded, error) { + event := new(LockReleaseTokenPoolRemotePoolAdded) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type LockReleaseTokenPoolRemotePoolRemovedIterator struct { + Event *LockReleaseTokenPoolRemotePoolRemoved contract *bind.BoundContract event string @@ -2707,7 +3007,7 @@ type LockReleaseTokenPoolRemotePoolSetIterator struct { fail error } -func (it *LockReleaseTokenPoolRemotePoolSetIterator) Next() bool { +func (it *LockReleaseTokenPoolRemotePoolRemovedIterator) Next() bool { if it.fail != nil { return false @@ -2716,7 +3016,7 @@ func (it *LockReleaseTokenPoolRemotePoolSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(LockReleaseTokenPoolRemotePoolSet) + it.Event = new(LockReleaseTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2731,7 +3031,7 @@ func (it *LockReleaseTokenPoolRemotePoolSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(LockReleaseTokenPoolRemotePoolSet) + it.Event = new(LockReleaseTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2746,44 +3046,43 @@ func (it *LockReleaseTokenPoolRemotePoolSetIterator) Next() bool { } } -func (it *LockReleaseTokenPoolRemotePoolSetIterator) Error() error { +func (it *LockReleaseTokenPoolRemotePoolRemovedIterator) Error() error { return it.fail } -func (it *LockReleaseTokenPoolRemotePoolSetIterator) Close() error { +func (it *LockReleaseTokenPoolRemotePoolRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type LockReleaseTokenPoolRemotePoolSet struct { +type LockReleaseTokenPoolRemotePoolRemoved struct { RemoteChainSelector uint64 - PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolSetIterator, error) { +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolRemovedIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _LockReleaseTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } - return &LockReleaseTokenPoolRemotePoolSetIterator{contract: _LockReleaseTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil + return &LockReleaseTokenPoolRemotePoolRemovedIterator{contract: _LockReleaseTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil } -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _LockReleaseTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2793,8 +3092,8 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolSet(op select { case log := <-logs: - event := new(LockReleaseTokenPoolRemotePoolSet) - if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + event := new(LockReleaseTokenPoolRemotePoolRemoved) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return err } event.Raw = log @@ -2815,9 +3114,9 @@ func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) WatchRemotePoolSet(op }), nil } -func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*LockReleaseTokenPoolRemotePoolSet, error) { - event := new(LockReleaseTokenPoolRemotePoolSet) - if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { +func (_LockReleaseTokenPool *LockReleaseTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*LockReleaseTokenPoolRemotePoolRemoved, error) { + event := new(LockReleaseTokenPoolRemotePoolRemoved) + if err := _LockReleaseTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return nil, err } event.Raw = log @@ -3089,10 +3388,14 @@ func (_LockReleaseTokenPool *LockReleaseTokenPool) ParseLog(log types.Log) (gene return _LockReleaseTokenPool.ParseOwnershipTransferRequested(log) case _LockReleaseTokenPool.abi.Events["OwnershipTransferred"].ID: return _LockReleaseTokenPool.ParseOwnershipTransferred(log) + case _LockReleaseTokenPool.abi.Events["RateLimitAdminSet"].ID: + return _LockReleaseTokenPool.ParseRateLimitAdminSet(log) case _LockReleaseTokenPool.abi.Events["Released"].ID: return _LockReleaseTokenPool.ParseReleased(log) - case _LockReleaseTokenPool.abi.Events["RemotePoolSet"].ID: - return _LockReleaseTokenPool.ParseRemotePoolSet(log) + case _LockReleaseTokenPool.abi.Events["RemotePoolAdded"].ID: + return _LockReleaseTokenPool.ParseRemotePoolAdded(log) + case _LockReleaseTokenPool.abi.Events["RemotePoolRemoved"].ID: + return _LockReleaseTokenPool.ParseRemotePoolRemoved(log) case _LockReleaseTokenPool.abi.Events["RouterUpdated"].ID: return _LockReleaseTokenPool.ParseRouterUpdated(log) case _LockReleaseTokenPool.abi.Events["TokensConsumed"].ID: @@ -3159,12 +3462,20 @@ func (LockReleaseTokenPoolOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (LockReleaseTokenPoolRateLimitAdminSet) Topic() common.Hash { + return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174") +} + func (LockReleaseTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (LockReleaseTokenPoolRemotePoolSet) Topic() common.Hash { - return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +func (LockReleaseTokenPoolRemotePoolAdded) Topic() common.Hash { + return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") +} + +func (LockReleaseTokenPoolRemotePoolRemoved) Topic() common.Hash { + return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") } func (LockReleaseTokenPoolRouterUpdated) Topic() common.Hash { @@ -3194,7 +3505,7 @@ type LockReleaseTokenPoolInterface interface { GetRebalancer(opts *bind.CallOpts) (common.Address, error) - GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) + GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3206,6 +3517,10 @@ type LockReleaseTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) + GetTokenDecimals(opts *bind.CallOpts) (uint8, error) + + IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) + IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -3218,9 +3533,11 @@ type LockReleaseTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) @@ -3228,14 +3545,14 @@ type LockReleaseTokenPoolInterface interface { ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) SetRebalancer(opts *bind.TransactOpts, rebalancer common.Address) (*types.Transaction, error) - SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferLiquidity(opts *bind.TransactOpts, from common.Address, amount *big.Int) (*types.Transaction, error) @@ -3328,17 +3645,29 @@ type LockReleaseTokenPoolInterface interface { ParseOwnershipTransferred(log types.Log) (*LockReleaseTokenPoolOwnershipTransferred, error) + FilterRateLimitAdminSet(opts *bind.FilterOpts) (*LockReleaseTokenPoolRateLimitAdminSetIterator, error) + + WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRateLimitAdminSet) (event.Subscription, error) + + ParseRateLimitAdminSet(log types.Log) (*LockReleaseTokenPoolRateLimitAdminSet, error) + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*LockReleaseTokenPoolReleasedIterator, error) WatchReleased(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) ParseReleased(log types.Log) (*LockReleaseTokenPoolReleased, error) - FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolSetIterator, error) + FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolAddedIterator, error) + + WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolAdded(log types.Log) (*LockReleaseTokenPoolRemotePoolAdded, error) + + FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*LockReleaseTokenPoolRemotePoolRemovedIterator, error) - WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *LockReleaseTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolSet(log types.Log) (*LockReleaseTokenPoolRemotePoolSet, error) + ParseRemotePoolRemoved(log types.Log) (*LockReleaseTokenPoolRemotePoolRemoved, error) FilterRouterUpdated(opts *bind.FilterOpts) (*LockReleaseTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/token_pool/token_pool.go b/core/gethwrappers/ccip/generated/token_pool/token_pool.go index 0bca23641c..5032b336e0 100644 --- a/core/gethwrappers/ccip/generated/token_pool/token_pool.go +++ b/core/gethwrappers/ccip/generated/token_pool/token_pool.go @@ -74,15 +74,14 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - Allowed bool - RemotePoolAddress []byte + RemotePoolAddresses [][]byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig } var TokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"lockOrBurnOut\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var TokenPoolABI = TokenPoolMetaData.ABI @@ -313,26 +312,26 @@ func (_TokenPool *TokenPoolCallerSession) GetRateLimitAdmin() (common.Address, e return _TokenPool.Contract.GetRateLimitAdmin(&_TokenPool.CallOpts) } -func (_TokenPool *TokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { +func (_TokenPool *TokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { var out []interface{} - err := _TokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + err := _TokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) if err != nil { - return *new([]byte), err + return *new([][]byte), err } - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) return out0, err } -func (_TokenPool *TokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _TokenPool.Contract.GetRemotePool(&_TokenPool.CallOpts, remoteChainSelector) +func (_TokenPool *TokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _TokenPool.Contract.GetRemotePools(&_TokenPool.CallOpts, remoteChainSelector) } -func (_TokenPool *TokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _TokenPool.Contract.GetRemotePool(&_TokenPool.CallOpts, remoteChainSelector) +func (_TokenPool *TokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _TokenPool.Contract.GetRemotePools(&_TokenPool.CallOpts, remoteChainSelector) } func (_TokenPool *TokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -445,6 +444,50 @@ func (_TokenPool *TokenPoolCallerSession) GetToken() (common.Address, error) { return _TokenPool.Contract.GetToken(&_TokenPool.CallOpts) } +func (_TokenPool *TokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _TokenPool.contract.Call(opts, &out, "getTokenDecimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_TokenPool *TokenPoolSession) GetTokenDecimals() (uint8, error) { + return _TokenPool.Contract.GetTokenDecimals(&_TokenPool.CallOpts) +} + +func (_TokenPool *TokenPoolCallerSession) GetTokenDecimals() (uint8, error) { + return _TokenPool.Contract.GetTokenDecimals(&_TokenPool.CallOpts) +} + +func (_TokenPool *TokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + var out []interface{} + err := _TokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_TokenPool *TokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _TokenPool.Contract.IsRemotePool(&_TokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_TokenPool *TokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _TokenPool.Contract.IsRemotePool(&_TokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + func (_TokenPool *TokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _TokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -545,6 +588,18 @@ func (_TokenPool *TokenPoolTransactorSession) AcceptOwnership() (*types.Transact return _TokenPool.Contract.AcceptOwnership(&_TokenPool.TransactOpts) } +func (_TokenPool *TokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_TokenPool *TokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.Contract.AddRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_TokenPool *TokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.Contract.AddRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_TokenPool *TokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -557,16 +612,16 @@ func (_TokenPool *TokenPoolTransactorSession) ApplyAllowListUpdates(removes []co return _TokenPool.Contract.ApplyAllowListUpdates(&_TokenPool.TransactOpts, removes, adds) } -func (_TokenPool *TokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _TokenPool.contract.Transact(opts, "applyChainUpdates", chains) +func (_TokenPool *TokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _TokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) } -func (_TokenPool *TokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, chains) +func (_TokenPool *TokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } -func (_TokenPool *TokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, chains) +func (_TokenPool *TokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _TokenPool.Contract.ApplyChainUpdates(&_TokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } func (_TokenPool *TokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -593,6 +648,18 @@ func (_TokenPool *TokenPoolTransactorSession) ReleaseOrMint(releaseOrMintIn Pool return _TokenPool.Contract.ReleaseOrMint(&_TokenPool.TransactOpts, releaseOrMintIn) } +func (_TokenPool *TokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_TokenPool *TokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.Contract.RemoveRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_TokenPool *TokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _TokenPool.Contract.RemoveRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_TokenPool *TokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -617,18 +684,6 @@ func (_TokenPool *TokenPoolTransactorSession) SetRateLimitAdmin(rateLimitAdmin c return _TokenPool.Contract.SetRateLimitAdmin(&_TokenPool.TransactOpts, rateLimitAdmin) } -func (_TokenPool *TokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_TokenPool *TokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.Contract.SetRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_TokenPool *TokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _TokenPool.Contract.SetRemotePool(&_TokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_TokenPool *TokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _TokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2025,6 +2080,123 @@ func (_TokenPool *TokenPoolFilterer) ParseOwnershipTransferred(log types.Log) (* return event, nil } +type TokenPoolRateLimitAdminSetIterator struct { + Event *TokenPoolRateLimitAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *TokenPoolRateLimitAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(TokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(TokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *TokenPoolRateLimitAdminSetIterator) Error() error { + return it.fail +} + +func (it *TokenPoolRateLimitAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type TokenPoolRateLimitAdminSet struct { + RateLimitAdmin common.Address + Raw types.Log +} + +func (_TokenPool *TokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*TokenPoolRateLimitAdminSetIterator, error) { + + logs, sub, err := _TokenPool.contract.FilterLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return &TokenPoolRateLimitAdminSetIterator{contract: _TokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil +} + +func (_TokenPool *TokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *TokenPoolRateLimitAdminSet) (event.Subscription, error) { + + logs, sub, err := _TokenPool.contract.WatchLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(TokenPoolRateLimitAdminSet) + if err := _TokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_TokenPool *TokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*TokenPoolRateLimitAdminSet, error) { + event := new(TokenPoolRateLimitAdminSet) + if err := _TokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type TokenPoolReleasedIterator struct { Event *TokenPoolReleased @@ -2162,8 +2334,136 @@ func (_TokenPool *TokenPoolFilterer) ParseReleased(log types.Log) (*TokenPoolRel return event, nil } -type TokenPoolRemotePoolSetIterator struct { - Event *TokenPoolRemotePoolSet +type TokenPoolRemotePoolAddedIterator struct { + Event *TokenPoolRemotePoolAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *TokenPoolRemotePoolAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(TokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(TokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *TokenPoolRemotePoolAddedIterator) Error() error { + return it.fail +} + +func (it *TokenPoolRemotePoolAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type TokenPoolRemotePoolAdded struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_TokenPool *TokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolAddedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _TokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &TokenPoolRemotePoolAddedIterator{contract: _TokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil +} + +func (_TokenPool *TokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _TokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(TokenPoolRemotePoolAdded) + if err := _TokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_TokenPool *TokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*TokenPoolRemotePoolAdded, error) { + event := new(TokenPoolRemotePoolAdded) + if err := _TokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type TokenPoolRemotePoolRemovedIterator struct { + Event *TokenPoolRemotePoolRemoved contract *bind.BoundContract event string @@ -2174,7 +2474,7 @@ type TokenPoolRemotePoolSetIterator struct { fail error } -func (it *TokenPoolRemotePoolSetIterator) Next() bool { +func (it *TokenPoolRemotePoolRemovedIterator) Next() bool { if it.fail != nil { return false @@ -2183,7 +2483,7 @@ func (it *TokenPoolRemotePoolSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(TokenPoolRemotePoolSet) + it.Event = new(TokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2198,7 +2498,7 @@ func (it *TokenPoolRemotePoolSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(TokenPoolRemotePoolSet) + it.Event = new(TokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2213,44 +2513,43 @@ func (it *TokenPoolRemotePoolSetIterator) Next() bool { } } -func (it *TokenPoolRemotePoolSetIterator) Error() error { +func (it *TokenPoolRemotePoolRemovedIterator) Error() error { return it.fail } -func (it *TokenPoolRemotePoolSetIterator) Close() error { +func (it *TokenPoolRemotePoolRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type TokenPoolRemotePoolSet struct { +type TokenPoolRemotePoolRemoved struct { RemoteChainSelector uint64 - PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_TokenPool *TokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolSetIterator, error) { +func (_TokenPool *TokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolRemovedIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _TokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _TokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } - return &TokenPoolRemotePoolSetIterator{contract: _TokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil + return &TokenPoolRemotePoolRemovedIterator{contract: _TokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil } -func (_TokenPool *TokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { +func (_TokenPool *TokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _TokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _TokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2260,8 +2559,8 @@ func (_TokenPool *TokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, si select { case log := <-logs: - event := new(TokenPoolRemotePoolSet) - if err := _TokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + event := new(TokenPoolRemotePoolRemoved) + if err := _TokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return err } event.Raw = log @@ -2282,9 +2581,9 @@ func (_TokenPool *TokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, si }), nil } -func (_TokenPool *TokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*TokenPoolRemotePoolSet, error) { - event := new(TokenPoolRemotePoolSet) - if err := _TokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { +func (_TokenPool *TokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*TokenPoolRemotePoolRemoved, error) { + event := new(TokenPoolRemotePoolRemoved) + if err := _TokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return nil, err } event.Raw = log @@ -2433,10 +2732,14 @@ func (_TokenPool *TokenPool) ParseLog(log types.Log) (generated.AbigenLog, error return _TokenPool.ParseOwnershipTransferRequested(log) case _TokenPool.abi.Events["OwnershipTransferred"].ID: return _TokenPool.ParseOwnershipTransferred(log) + case _TokenPool.abi.Events["RateLimitAdminSet"].ID: + return _TokenPool.ParseRateLimitAdminSet(log) case _TokenPool.abi.Events["Released"].ID: return _TokenPool.ParseReleased(log) - case _TokenPool.abi.Events["RemotePoolSet"].ID: - return _TokenPool.ParseRemotePoolSet(log) + case _TokenPool.abi.Events["RemotePoolAdded"].ID: + return _TokenPool.ParseRemotePoolAdded(log) + case _TokenPool.abi.Events["RemotePoolRemoved"].ID: + return _TokenPool.ParseRemotePoolRemoved(log) case _TokenPool.abi.Events["RouterUpdated"].ID: return _TokenPool.ParseRouterUpdated(log) @@ -2489,12 +2792,20 @@ func (TokenPoolOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (TokenPoolRateLimitAdminSet) Topic() common.Hash { + return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174") +} + func (TokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (TokenPoolRemotePoolSet) Topic() common.Hash { - return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +func (TokenPoolRemotePoolAdded) Topic() common.Hash { + return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") +} + +func (TokenPoolRemotePoolRemoved) Topic() common.Hash { + return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") } func (TokenPoolRouterUpdated) Topic() common.Hash { @@ -2516,7 +2827,7 @@ type TokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) + GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -2528,6 +2839,10 @@ type TokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) + GetTokenDecimals(opts *bind.CallOpts) (uint8, error) + + IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) + IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -2538,20 +2853,22 @@ type TokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) - SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -2622,17 +2939,29 @@ type TokenPoolInterface interface { ParseOwnershipTransferred(log types.Log) (*TokenPoolOwnershipTransferred, error) + FilterRateLimitAdminSet(opts *bind.FilterOpts) (*TokenPoolRateLimitAdminSetIterator, error) + + WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *TokenPoolRateLimitAdminSet) (event.Subscription, error) + + ParseRateLimitAdminSet(log types.Log) (*TokenPoolRateLimitAdminSet, error) + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*TokenPoolReleasedIterator, error) WatchReleased(opts *bind.WatchOpts, sink chan<- *TokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) ParseReleased(log types.Log) (*TokenPoolReleased, error) - FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolSetIterator, error) + FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolAddedIterator, error) + + WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolAdded(log types.Log) (*TokenPoolRemotePoolAdded, error) + + FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*TokenPoolRemotePoolRemovedIterator, error) - WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *TokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolSet(log types.Log) (*TokenPoolRemotePoolSet, error) + ParseRemotePoolRemoved(log types.Log) (*TokenPoolRemotePoolRemoved, error) FilterRouterUpdated(opts *bind.FilterOpts) (*TokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go index 3e754d5cb7..ca6c4a1977 100644 --- a/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go +++ b/core/gethwrappers/ccip/generated/usdc_token_pool/usdc_token_pool.go @@ -74,8 +74,7 @@ type RateLimiterTokenBucket struct { type TokenPoolChainUpdate struct { RemoteChainSelector uint64 - Allowed bool - RemotePoolAddress []byte + RemotePoolAddresses [][]byte RemoteTokenAddress []byte OutboundRateLimiterConfig RateLimiterConfig InboundRateLimiterConfig RateLimiterConfig @@ -95,8 +94,8 @@ type USDCTokenPoolDomainUpdate struct { } var USDCTokenPoolMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"previousPoolAddress\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chains\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePool\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"setRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101406040523480156200001257600080fd5b50604051620052c6380380620052c6833981016040819052620000359162000b4c565b838383833380600081620000905760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c357620000c3816200041b565b5050506001600160a01b0384161580620000e457506001600160a01b038116155b80620000f757506001600160a01b038216155b1562000116576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0384811660805282811660a052600480546001600160a01b031916918316919091179055825115801560c0526200016957604080516000815260208101909152620001699084620004c6565b5050506001600160a01b038616905062000196576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001d7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001fd919062000c72565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000240573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000266919062000c99565b905063ffffffff81161562000297576040516334697c6b60e11b815263ffffffff8216600482015260240162000087565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002fe919062000c99565b905063ffffffff8116156200032f576040516316ba39c560e31b815263ffffffff8216600482015260240162000087565b6001600160a01b0380891660e05283166101008190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa15801562000381573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003a7919062000c99565b63ffffffff166101205260e051608051620003d1916001600160a01b039091169060001962000623565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000de6565b336001600160a01b03821603620004755760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000087565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60c051620004e7576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005725760008382815181106200050b576200050b62000cc1565b602090810291909101015190506200052560028262000709565b1562000568576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101620004ea565b5060005b81518110156200061e57600082828151811062000597576200059762000cc1565b6020026020010151905060006001600160a01b0316816001600160a01b031603620005c3575062000615565b620005d060028262000729565b1562000613576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010162000576565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa15801562000675573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200069b919062000cd7565b620006a7919062000d07565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915291925062000703918691906200074016565b50505050565b600062000720836001600160a01b03841662000811565b90505b92915050565b600062000720836001600160a01b03841662000915565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564908201526000906200078f906001600160a01b03851690849062000967565b8051909150156200061e5780806020019051810190620007b0919062000d1d565b6200061e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000087565b600081815260018301602052604081205480156200090a5760006200083860018362000d41565b85549091506000906200084e9060019062000d41565b9050808214620008ba57600086600001828154811062000872576200087262000cc1565b906000526020600020015490508087600001848154811062000898576200089862000cc1565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620008ce57620008ce62000d57565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000723565b600091505062000723565b60008181526001830160205260408120546200095e5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000723565b50600062000723565b606062000978848460008562000980565b949350505050565b606082471015620009e35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000087565b600080866001600160a01b0316858760405162000a01919062000d93565b60006040518083038185875af1925050503d806000811462000a40576040519150601f19603f3d011682016040523d82523d6000602084013e62000a45565b606091505b50909250905062000a598783838762000a64565b979650505050505050565b6060831562000ad857825160000362000ad0576001600160a01b0385163b62000ad05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000087565b508162000978565b62000978838381511562000aef5781518083602001fd5b8060405162461bcd60e51b815260040162000087919062000db1565b6001600160a01b038116811462000b2157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b478162000b0b565b919050565b600080600080600060a0868803121562000b6557600080fd5b855162000b728162000b0b565b8095505060208087015162000b878162000b0b565b60408801519095506001600160401b038082111562000ba557600080fd5b818901915089601f83011262000bba57600080fd5b81518181111562000bcf5762000bcf62000b24565b8060051b604051601f19603f8301168101818110858211171562000bf75762000bf762000b24565b60405291825284820192508381018501918c83111562000c1657600080fd5b938501935b8285101562000c3f5762000c2f8562000b3a565b8452938501939285019262000c1b565b80985050505050505062000c566060870162000b3a565b915062000c666080870162000b3a565b90509295509295909350565b60006020828403121562000c8557600080fd5b815162000c928162000b0b565b9392505050565b60006020828403121562000cac57600080fd5b815163ffffffff8116811462000c9257600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000cea57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111562000723576200072362000cf1565b60006020828403121562000d3057600080fd5b8151801515811462000c9257600080fd5b8181038181111562000723576200072362000cf1565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000d8a57818101518382015260200162000d70565b50506000910152565b6000825162000da781846020870162000d6d565b9190910192915050565b602081526000825180602084015262000dd281604085016020870162000d6d565b601f01601f19169190910160400192915050565b60805160a05160c05160e051610100516101205161442762000e9f60003960008181610382015281816111d101528181611e4a0152611ea80152600081816106760152610a7801526000818161035b01526110e701526000818161063a01528181611f45015261288001526000818161057601528181611c4801526121fb01526000818161028f015281816102e4015281816110b101528181611b680152818161211b015281816128160152612a6b01526144276000f3fe608060405234801561001057600080fd5b50600436106101ef5760003560e01c80639a4575b91161010f578063c75eea9c116100a2578063dfadfa3511610071578063dfadfa351461059a578063e0351e1314610638578063f2fde38b1461065e578063fbf84dd71461067157600080fd5b8063c75eea9c1461053b578063cf7401f31461054e578063db6327dc14610561578063dc0bd9711461057457600080fd5b8063b0f479a1116100de578063b0f479a1146104e2578063b794658014610500578063c0d7865514610513578063c4bffe2b1461052657600080fd5b80639a4575b9146104365780639fdf13ff14610456578063a7cd63b71461045e578063af58d59f1461047357600080fd5b80636155cda01161018757806379ba50971161015657806379ba5097146103ea5780637d54534e146103f25780638926f54f146104055780638da5cb5b1461041857600080fd5b80636155cda0146103565780636b716b0d1461037d5780636d3d1a58146103b957806378a010b2146103d757600080fd5b806321df0da7116101c357806321df0da71461028d578063240028e8146102d4578063390775371461032157806354c8a4f31461034357600080fd5b806241d3c1146101f457806301ffc9a7146102095780630a2fd49314610231578063181f5a7714610251575b600080fd5b61020761020236600461320e565b610698565b005b61021c610217366004613283565b610835565b60405190151581526020015b60405180910390f35b61024461023f3660046132eb565b61091a565b604051610228919061336c565b6102446040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e300000000000000000000000000081525081565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610228565b61021c6102e23660046133ac565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b61033461032f3660046133c9565b6109ca565b60405190518152602001610228565b610207610351366004613451565b610bb7565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b6103a47f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610228565b60085473ffffffffffffffffffffffffffffffffffffffff166102af565b6102076103e53660046134bd565b610c32565b610207610da1565b6102076104003660046133ac565b610e9e565b61021c6104133660046132eb565b610eed565b60005473ffffffffffffffffffffffffffffffffffffffff166102af565b610449610444366004613542565b610f04565b604051610228919061357d565b6103a4600081565b61046661124c565b60405161022891906135dd565b6104866104813660046132eb565b61125d565b604051610228919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102af565b61024461050e3660046132eb565b611332565b6102076105213660046133ac565b61135d565b61052e611431565b6040516102289190613637565b6104866105493660046132eb565b6114e9565b61020761055c3660046137c2565b6115bb565b61020761056f366004613809565b611644565b7f00000000000000000000000000000000000000000000000000000000000000006102af565b61060e6105a83660046132eb565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600982529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610228565b7f000000000000000000000000000000000000000000000000000000000000000061021c565b61020761066c3660046133ac565b611aca565b6102af7f000000000000000000000000000000000000000000000000000000000000000081565b6106a0611ade565b60005b818110156107f75760008383838181106106bf576106bf61384b565b9050608002018036038101906106d5919061388e565b805190915015806106f25750604081015167ffffffffffffffff16155b1561076157604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600990925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169190931617929092179055016106a3565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee568282604051610829929190613908565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf0000000000000000000000000000000000000000000000000000000014806108c857507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b8061091457507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b67ffffffffffffffff811660009081526007602052604090206004018054606091906109459061398f565b80601f01602080910402602001604051908101604052809291908181526020018280546109719061398f565b80156109be5780601f10610993576101008083540402835291602001916109be565b820191906000526020600020905b8154815290600101906020018083116109a157829003601f168201915b50505050509050919050565b6040805160208101909152600081526109ea6109e583613a8d565b611b61565b60006109f960c0840184613b82565b810190610a069190613be7565b90506000610a1760e0850185613b82565b810190610a249190613c26565b9050610a34816000015183611d92565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610aab92600401613cb7565b6020604051808303816000875af1158015610aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aee9190613cdc565b610b24576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3460608501604086016133ac565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9691815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b610bbf611ade565b610c2c84848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808802828101820190935287825290935087925086918291850190849080828437600092019190915250611f4392505050565b50505050565b610c3a611ade565b610c4383610eed565b610c85576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610758565b67ffffffffffffffff831660009081526007602052604081206004018054610cac9061398f565b80601f0160208091040260200160405190810160405280929190818152602001828054610cd89061398f565b8015610d255780601f10610cfa57610100808354040283529160200191610d25565b820191906000526020600020905b815481529060010190602001808311610d0857829003601f168201915b5050505067ffffffffffffffff8616600090815260076020526040902091925050600401610d54838583613d41565b508367ffffffffffffffff167fdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf828585604051610d9393929190613ea5565b60405180910390a250505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610758565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ea6611ade565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000610914600567ffffffffffffffff84166120f9565b6040805180820190915260608082526020820152610f29610f2483613ed5565b612114565b6000600981610f3e60408601602087016132eb565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610fe557610fa660408401602085016132eb565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b610fef8380613b82565b9050602014611036576110028380613b82565b6040517fa3c8cf09000000000000000000000000000000000000000000000000000000008152600401610758929190613f79565b60006110428480613b82565b81019061104f9190613f8d565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af1158015611130573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111549190613fa6565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a260405180604001604052806111b187602001602081019061050e91906132eb565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b606061125860026122de565b905090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526003909101548084166060830152919091049091166080820152610914906122eb565b67ffffffffffffffff811660009081526007602052604090206005018054606091906109459061398f565b611365611ade565b73ffffffffffffffffffffffffffffffffffffffff81166113b2576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f16849101610829565b6060600061143f60056122de565b90506000815167ffffffffffffffff81111561145d5761145d613679565b604051908082528060200260200182016040528015611486578160200160208202803683370190505b50905060005b82518110156114e2578281815181106114a7576114a761384b565b60200260200101518282815181106114c1576114c161384b565b67ffffffffffffffff9092166020928302919091019091015260010161148c565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff161515948201949094526001909101548084166060830152919091049091166080820152610914906122eb565b60085473ffffffffffffffffffffffffffffffffffffffff1633148015906115fb575060005473ffffffffffffffffffffffffffffffffffffffff163314155b15611634576040517f8e4a23d6000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b61163f83838361239d565b505050565b61164c611ade565b60005b8181101561163f57600083838381811061166b5761166b61384b565b905060200281019061167d9190613fc3565b61168690614001565b905061169b8160800151826020015115612487565b6116ae8160a00151826020015115612487565b8060200151156119aa5780516116d09060059067ffffffffffffffff166125c0565b6117155780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b604081015151158061172a5750606081015151155b15611761576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252608083810180516020908101516fffffffffffffffffffffffffffffffff9081168486019081524263ffffffff90811660a0808901829052865151151560c08a01528651860151851660e08a015295518901518416610100890152918752875180860189529489018051850151841686528585019290925281515115158589015281518401518316606080870191909152915188015183168587015283870194855288880151878901908152828a015183890152895167ffffffffffffffff1660009081526007865289902088518051825482890151838e01519289167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316177001000000000000000000000000000000009188168202177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff90811674010000000000000000000000000000000000000000941515850217865584890151948d0151948a16948a168202949094176001860155995180516002860180549b8301519f830151918b169b9093169a909a179d9096168a029c909c1790911696151502959095179098559081015194015193811693169091029190911760038201559151909190600482019061194290826140b5565b506060820151600582019061195790826140b5565b505081516060830151608084015160a08501516040517f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c2955061199d94939291906141cf565b60405180910390a1611ac1565b80516119c29060059067ffffffffffffffff166125cc565b611a075780516040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610758565b805167ffffffffffffffff16600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611a7060048301826131c0565b611a7e6005830160006131c0565b5050805160405167ffffffffffffffff90911681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d8599169060200160405180910390a15b5060010161164f565b611ad2611ade565b611adb816125d8565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611b5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610758565b565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614611bf65760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610758565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015611ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc89190613cdc565b15611cff576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611d0c81602001516126cd565b6000611d1b826020015161091a565b9050805160001480611d3f575080805190602001208260a001518051906020012014155b15611d7c578160a001516040517f24eb47e5000000000000000000000000000000000000000000000000000000008152600401610758919061336c565b611d8e826020015183606001516127f3565b5050565b600482015163ffffffff811615611ddd576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff82166004820152602401610758565b6008830151600c8401516014850151602085015163ffffffff808516911614611e485760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff91821660048201529084166024820152604401610758565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff1614611edd576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116600483015283166024820152604401610758565b845167ffffffffffffffff828116911614611f3b5784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff91821660048201529082166024820152604401610758565b505050505050565b7f0000000000000000000000000000000000000000000000000000000000000000611f9a576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8251811015612030576000838281518110611fba57611fba61384b565b60200260200101519050611fd881600261283a90919063ffffffff16565b156120275760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101611f9d565b5060005b815181101561163f5760008282815181106120515761205161384b565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361209557506120f1565b6120a060028261285c565b156120ef5760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101612034565b600081815260018301602052604081205415155b9392505050565b60808101517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff9081169116146121a95760808101516040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610758565b60208101516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815260809190911b77ffffffffffffffff000000000000000000000000000000001660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690632cbc26bb90602401602060405180830381865afa158015612257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227b9190613cdc565b156122b2576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122bf816040015161287e565b6122cc81602001516128fd565b611adb81602001518260600151612a4b565b6060600061210d83612a8f565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261237982606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261235d9190614297565b85608001516fffffffffffffffffffffffffffffffff16612aea565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b6123a683610eed565b6123e8576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610758565b6123f3826000612487565b67ffffffffffffffff831660009081526007602052604090206124169083612b14565b612421816000612487565b67ffffffffffffffff831660009081526007602052604090206124479060020182612b14565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b83838360405161247a939291906142aa565b60405180910390a1505050565b81511561254e5781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff161015806124dd575060408201516fffffffffffffffffffffffffffffffff16155b1561251657816040517f8020d124000000000000000000000000000000000000000000000000000000008152600401610758919061432d565b8015611d8e576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516fffffffffffffffffffffffffffffffff16151580612587575060208201516fffffffffffffffffffffffffffffffff1615155b15611d8e57816040517fd68af9cc000000000000000000000000000000000000000000000000000000008152600401610758919061432d565b600061210d8383612cb6565b600061210d8383612d05565b3373ffffffffffffffffffffffffffffffffffffffff821603612657576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610758565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6126d681610eed565b612718576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610758565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612797573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127bb9190613cdc565b611adb576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b67ffffffffffffffff82166000908152600760205260409020611d8e90600201827f0000000000000000000000000000000000000000000000000000000000000000612df8565b600061210d8373ffffffffffffffffffffffffffffffffffffffff8416612d05565b600061210d8373ffffffffffffffffffffffffffffffffffffffff8416612cb6565b7f000000000000000000000000000000000000000000000000000000000000000015611adb576128af60028261317b565b611adb576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610758565b61290681610eed565b612948576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610758565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa1580156129c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e59190614369565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611adb576040517f728fe07b000000000000000000000000000000000000000000000000000000008152336004820152602401610758565b67ffffffffffffffff82166000908152600760205260409020611d8e90827f0000000000000000000000000000000000000000000000000000000000000000612df8565b6060816000018054806020026020016040519081016040528092919081815260200182805480156109be57602002820191906000526020600020905b815481526020019060010190808311612acb5750505050509050919050565b6000612b0985612afa8486614386565b612b04908761439d565b6131aa565b90505b949350505050565b8154600090612b3d90700100000000000000000000000000000000900463ffffffff1642614297565b90508015612bdf5760018301548354612b85916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612aea565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354612c05916fffffffffffffffffffffffffffffffff90811691166131aa565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061247a90849061432d565b6000818152600183016020526040812054612cfd57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610914565b506000610914565b60008181526001830160205260408120548015612dee576000612d29600183614297565b8554909150600090612d3d90600190614297565b9050808214612da2576000866000018281548110612d5d57612d5d61384b565b9060005260206000200154905080876000018481548110612d8057612d8061384b565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612db357612db36143b0565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610914565b6000915050610914565b825474010000000000000000000000000000000000000000900460ff161580612e1f575081155b15612e2957505050565b825460018401546fffffffffffffffffffffffffffffffff80831692911690600090612e6f90700100000000000000000000000000000000900463ffffffff1642614297565b90508015612f2f5781831115612eb1576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001860154612eeb9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612aea565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b84821015612fe65773ffffffffffffffffffffffffffffffffffffffff8416612f8e576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610758565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610758565b848310156130f95760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1690600090829061302a9082614297565b613034878a614297565b61303e919061439d565b61304891906143df565b905073ffffffffffffffffffffffffffffffffffffffff86166130a1576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610758565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610758565b6131038584614297565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561210d565b60008183106131b9578161210d565b5090919050565b5080546131cc9061398f565b6000825580601f106131dc575050565b601f016020900490600052602060002090810190611adb91905b8082111561320a57600081556001016131f6565b5090565b6000806020838503121561322157600080fd5b823567ffffffffffffffff8082111561323957600080fd5b818501915085601f83011261324d57600080fd5b81358181111561325c57600080fd5b8660208260071b850101111561327157600080fd5b60209290920196919550909350505050565b60006020828403121561329557600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461210d57600080fd5b67ffffffffffffffff81168114611adb57600080fd5b80356132e6816132c5565b919050565b6000602082840312156132fd57600080fd5b813561210d816132c5565b6000815180845260005b8181101561332e57602081850181015186830182015201613312565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061210d6020830184613308565b73ffffffffffffffffffffffffffffffffffffffff81168114611adb57600080fd5b80356132e68161337f565b6000602082840312156133be57600080fd5b813561210d8161337f565b6000602082840312156133db57600080fd5b813567ffffffffffffffff8111156133f257600080fd5b8201610100818503121561210d57600080fd5b60008083601f84011261341757600080fd5b50813567ffffffffffffffff81111561342f57600080fd5b6020830191508360208260051b850101111561344a57600080fd5b9250929050565b6000806000806040858703121561346757600080fd5b843567ffffffffffffffff8082111561347f57600080fd5b61348b88838901613405565b909650945060208701359150808211156134a457600080fd5b506134b187828801613405565b95989497509550505050565b6000806000604084860312156134d257600080fd5b83356134dd816132c5565b9250602084013567ffffffffffffffff808211156134fa57600080fd5b818601915086601f83011261350e57600080fd5b81358181111561351d57600080fd5b87602082850101111561352f57600080fd5b6020830194508093505050509250925092565b60006020828403121561355457600080fd5b813567ffffffffffffffff81111561356b57600080fd5b820160a0818503121561210d57600080fd5b6020815260008251604060208401526135996060840182613308565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160408501526135d48282613308565b95945050505050565b6020808252825182820181905260009190848201906040850190845b8181101561362b57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016135f9565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561362b57835167ffffffffffffffff1683529284019291840191600101613653565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156136cc576136cc613679565b60405290565b6040805190810167ffffffffffffffff811182821017156136cc576136cc613679565b60405160c0810167ffffffffffffffff811182821017156136cc576136cc613679565b8015158114611adb57600080fd5b80356132e681613718565b80356fffffffffffffffffffffffffffffffff811681146132e657600080fd5b60006060828403121561376357600080fd5b6040516060810181811067ffffffffffffffff8211171561378657613786613679565b604052905080823561379781613718565b81526137a560208401613731565b60208201526137b660408401613731565b60408201525092915050565b600080600060e084860312156137d757600080fd5b83356137e2816132c5565b92506137f18560208601613751565b91506138008560808601613751565b90509250925092565b6000806020838503121561381c57600080fd5b823567ffffffffffffffff81111561383357600080fd5b61383f85828601613405565b90969095509350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff811681146132e657600080fd5b6000608082840312156138a057600080fd5b6040516080810181811067ffffffffffffffff821117156138c3576138c3613679565b604052823581526138d66020840161387a565b602082015260408301356138e9816132c5565b604082015260608301356138fc81613718565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613982578135835263ffffffff61393a86840161387a565b16858401528382013561394c816132c5565b67ffffffffffffffff168385015260608281013561396981613718565b151590840152608092830192919091019060010161391e565b5090979650505050505050565b600181811c908216806139a357607f821691505b6020821081036139dc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600082601f8301126139f357600080fd5b813567ffffffffffffffff80821115613a0e57613a0e613679565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715613a5457613a54613679565b81604052838152866020858801011115613a6d57600080fd5b836020870160208301376000602085830101528094505050505092915050565b60006101008236031215613aa057600080fd5b613aa86136a8565b823567ffffffffffffffff80821115613ac057600080fd5b613acc368387016139e2565b8352613ada602086016132db565b6020840152613aeb604086016133a1565b604084015260608501356060840152613b06608086016133a1565b608084015260a0850135915080821115613b1f57600080fd5b613b2b368387016139e2565b60a084015260c0850135915080821115613b4457600080fd5b613b50368387016139e2565b60c084015260e0850135915080821115613b6957600080fd5b50613b76368286016139e2565b60e08301525092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613bb757600080fd5b83018035915067ffffffffffffffff821115613bd257600080fd5b60200191503681900382131561344a57600080fd5b600060408284031215613bf957600080fd5b613c016136d2565b8235613c0c816132c5565b8152613c1a6020840161387a565b60208201529392505050565b600060208284031215613c3857600080fd5b813567ffffffffffffffff80821115613c5057600080fd5b9083019060408286031215613c6457600080fd5b613c6c6136d2565b823582811115613c7b57600080fd5b613c87878286016139e2565b825250602083013582811115613c9c57600080fd5b613ca8878286016139e2565b60208301525095945050505050565b604081526000613cca6040830185613308565b82810360208401526135d48185613308565b600060208284031215613cee57600080fd5b815161210d81613718565b601f82111561163f576000816000526020600020601f850160051c81016020861015613d225750805b601f850160051c820191505b81811015611f3b57828155600101613d2e565b67ffffffffffffffff831115613d5957613d59613679565b613d6d83613d67835461398f565b83613cf9565b6000601f841160018114613dbf5760008515613d895750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613e55565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015613e0e5786850135825560209485019460019092019101613dee565b5086821015613e49577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b604081526000613eb86040830186613308565b8281036020840152613ecb818587613e5c565b9695505050505050565b600060a08236031215613ee757600080fd5b60405160a0810167ffffffffffffffff8282108183111715613f0b57613f0b613679565b816040528435915080821115613f2057600080fd5b50613f2d368286016139e2565b8252506020830135613f3e816132c5565b60208201526040830135613f518161337f565b6040820152606083810135908201526080830135613f6e8161337f565b608082015292915050565b602081526000612b0c602083018486613e5c565b600060208284031215613f9f57600080fd5b5035919050565b600060208284031215613fb857600080fd5b815161210d816132c5565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec1833603018112613ff757600080fd5b9190910192915050565b6000610140823603121561401457600080fd5b61401c6136f5565b614025836132db565b815261403360208401613726565b6020820152604083013567ffffffffffffffff8082111561405357600080fd5b61405f368387016139e2565b6040840152606085013591508082111561407857600080fd5b50614085368286016139e2565b6060830152506140983660808501613751565b60808201526140aa3660e08501613751565b60a082015292915050565b815167ffffffffffffffff8111156140cf576140cf613679565b6140e3816140dd845461398f565b84613cf9565b602080601f83116001811461413657600084156141005750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611f3b565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561418357888601518255948401946001909101908401614164565b50858210156141bf57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526141f381840187613308565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506142319050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e08301526135d4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561091457610914614268565b67ffffffffffffffff8416815260e081016142f660208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152612b0c565b6060810161091482848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561437b57600080fd5b815161210d8161337f565b808202811582820484141761091457610914614268565b8082018082111561091457610914614268565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600082614415577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"tokenMessenger\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"allowlist\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"AllowListNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"CallerIsNotARampOnRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotTransferToSelf\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"DisabledNonZeroRateLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"expected\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"actual\",\"type\":\"uint8\"}],\"name\":\"InvalidDecimalArgs\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidDestinationDomain\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate\",\"name\":\"domain\",\"type\":\"tuple\"}],\"name\":\"InvalidDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidMessageVersion\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"}],\"name\":\"InvalidNonce\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"InvalidRateLimitRate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"}],\"name\":\"InvalidRemoteChainDecimals\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidRemotePoolForChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"expected\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"got\",\"type\":\"uint32\"}],\"name\":\"InvalidSourceDomain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidSourcePoolAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"}],\"name\":\"InvalidTokenMessengerVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeProposedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"NonExistentChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"remoteDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"localDecimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"remoteAmount\",\"type\":\"uint256\"}],\"name\":\"OverflowDetected\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OwnerCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"PoolAlreadyAdded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RateLimitMustBeDisabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"domain\",\"type\":\"uint64\"}],\"name\":\"UnknownDomain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnlockingUSDCFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListAdd\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AllowListRemove\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Burned\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenMessenger\",\"type\":\"address\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"name\":\"DomainsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Locked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Minted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"RateLimitAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Released\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"RemotePoolRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldRouter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"RouterUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUPPORTED_USDC_VERSION\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"addRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"removes\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"adds\",\"type\":\"address[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"remoteChainSelectorsToRemove\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes[]\",\"name\":\"remotePoolAddresses\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"remoteTokenAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundRateLimiterConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundRateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structTokenPool.ChainUpdate[]\",\"name\":\"chainsToAdd\",\"type\":\"tuple[]\"}],\"name\":\"applyChainUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowListEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentInboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getCurrentOutboundRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"getDomain\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.Domain\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRateLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemotePools\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRemoteToken\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRmnProxy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSupportedChains\",\"outputs\":[{\"internalType\":\"uint64[]\",\"name\":\"\",\"type\":\"uint64[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDecimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_localDomainIdentifier\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_messageTransmitter\",\"outputs\":[{\"internalType\":\"contractIMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_tokenMessenger\",\"outputs\":[{\"internalType\":\"contractITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"isRemotePool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"isSupportedChain\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isSupportedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structPool.LockOrBurnInV1\",\"name\":\"lockOrBurnIn\",\"type\":\"tuple\"}],\"name\":\"lockOrBurn\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destPoolData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.LockOrBurnOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"originalSender\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"sourcePoolData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainTokenData\",\"type\":\"bytes\"}],\"internalType\":\"structPool.ReleaseOrMintInV1\",\"name\":\"releaseOrMintIn\",\"type\":\"tuple\"}],\"name\":\"releaseOrMint\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destinationAmount\",\"type\":\"uint256\"}],\"internalType\":\"structPool.ReleaseOrMintOutV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"remotePoolAddress\",\"type\":\"bytes\"}],\"name\":\"removeRemotePool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"outboundConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"inboundConfig\",\"type\":\"tuple\"}],\"name\":\"setChainRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"allowedCaller\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"domainIdentifier\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"internalType\":\"structUSDCTokenPool.DomainUpdate[]\",\"name\":\"domains\",\"type\":\"tuple[]\"}],\"name\":\"setDomains\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"rateLimitAdmin\",\"type\":\"address\"}],\"name\":\"setRateLimitAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newRouter\",\"type\":\"address\"}],\"name\":\"setRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101606040523480156200001257600080fd5b50604051620054b7380380620054b7833981016040819052620000359162000b93565b836006848484336000816200005d57604051639b15e16f60e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b03848116919091179091558116156200009057620000908162000493565b50506001600160a01b0385161580620000b057506001600160a01b038116155b80620000c357506001600160a01b038216155b15620000e2576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b03808616608081905290831660c0526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa92505050801562000152575060408051601f3d908101601f191682019092526200014f9181019062000cb9565b60015b1562000193578060ff168560ff161462000191576040516332ad3e0760e11b815260ff8087166004830152821660248201526044015b60405180910390fd5b505b60ff841660a052600480546001600160a01b0319166001600160a01b038316179055825115801560e052620001dd57604080516000815260208101909152620001dd90846200050d565b5050506001600160a01b03871691506200020c9050576040516306b7c75960e31b815260040160405180910390fd5b6000856001600160a01b0316632c1219216040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200024d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000273919062000ce5565b90506000816001600160a01b03166354fd4d506040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002b6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002dc919062000d05565b905063ffffffff8116156200030d576040516334697c6b60e11b815263ffffffff8216600482015260240162000188565b6000876001600160a01b0316639cdbb1816040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200034e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000374919062000d05565b905063ffffffff811615620003a5576040516316ba39c560e31b815263ffffffff8216600482015260240162000188565b6001600160a01b038089166101005283166101208190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa158015620003f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041e919062000d05565b63ffffffff16610140526101005160805162000449916001600160a01b03909116906000196200066a565b6040516001600160a01b03891681527f2e902d38f15b233cbb63711add0fca4545334d3a169d60c0a616494d7eea95449060200160405180910390a1505050505050505062000e52565b336001600160a01b03821603620004bd57604051636d6c4ee560e11b815260040160405180910390fd5b600080546001600160a01b0319166001600160a01b03838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60e0516200052e576040516335f4a7b360e01b815260040160405180910390fd5b60005b8251811015620005b957600083828151811062000552576200055262000d2d565b602090810291909101015190506200056c60028262000750565b15620005af576040516001600160a01b03821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b5060010162000531565b5060005b815181101562000665576000828281518110620005de57620005de62000d2d565b6020026020010151905060006001600160a01b0316816001600160a01b0316036200060a57506200065c565b6200061760028262000770565b156200065a576040516001600160a01b03821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b600101620005bd565b505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015620006bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620006e2919062000d43565b620006ee919062000d73565b604080516001600160a01b038616602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091529192506200074a918691906200078716565b50505050565b600062000767836001600160a01b03841662000858565b90505b92915050565b600062000767836001600160a01b0384166200095c565b6040805180820190915260208082527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490820152600090620007d6906001600160a01b038516908490620009ae565b805190915015620006655780806020019051810190620007f7919062000d89565b620006655760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000188565b60008181526001830160205260408120548015620009515760006200087f60018362000dad565b8554909150600090620008959060019062000dad565b905080821462000901576000866000018281548110620008b957620008b962000d2d565b9060005260206000200154905080876000018481548110620008df57620008df62000d2d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000915576200091562000dc3565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200076a565b60009150506200076a565b6000818152600183016020526040812054620009a5575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200076a565b5060006200076a565b6060620009bf8484600085620009c7565b949350505050565b60608247101562000a2a5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000188565b600080866001600160a01b0316858760405162000a48919062000dff565b60006040518083038185875af1925050503d806000811462000a87576040519150601f19603f3d011682016040523d82523d6000602084013e62000a8c565b606091505b50909250905062000aa08783838762000aab565b979650505050505050565b6060831562000b1f57825160000362000b17576001600160a01b0385163b62000b175760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000188565b5081620009bf565b620009bf838381511562000b365781518083602001fd5b8060405162461bcd60e51b815260040162000188919062000e1d565b6001600160a01b038116811462000b6857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b805162000b8e8162000b52565b919050565b600080600080600060a0868803121562000bac57600080fd5b855162000bb98162000b52565b8095505060208087015162000bce8162000b52565b60408801519095506001600160401b038082111562000bec57600080fd5b818901915089601f83011262000c0157600080fd5b81518181111562000c165762000c1662000b6b565b8060051b604051601f19603f8301168101818110858211171562000c3e5762000c3e62000b6b565b60405291825284820192508381018501918c83111562000c5d57600080fd5b938501935b8285101562000c865762000c768562000b81565b8452938501939285019262000c62565b80985050505050505062000c9d6060870162000b81565b915062000cad6080870162000b81565b90509295509295909350565b60006020828403121562000ccc57600080fd5b815160ff8116811462000cde57600080fd5b9392505050565b60006020828403121562000cf857600080fd5b815162000cde8162000b52565b60006020828403121562000d1857600080fd5b815163ffffffff8116811462000cde57600080fd5b634e487b7160e01b600052603260045260246000fd5b60006020828403121562000d5657600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156200076a576200076a62000d5d565b60006020828403121562000d9c57600080fd5b8151801515811462000cde57600080fd5b818103818111156200076a576200076a62000d5d565b634e487b7160e01b600052603160045260246000fd5b60005b8381101562000df657818101518382015260200162000ddc565b50506000910152565b6000825162000e1381846020870162000dd9565b9190910192915050565b602081526000825180602084015262000e3e81604085016020870162000dd9565b601f01601f19169190910160400192915050565b60805160a05160c05160e0516101005161012051610140516145af62000f08600039600081816104170152818161113c01528181612107015261216501526000818161072b0152610a750152600081816103dd01526110520152600081816106dc0152818161221d0152612bcc01526000818161061801528181611eb40152612509015260006103660152600081816102cd015281816103220152818161101c01528181612b620152612db701526145af6000f3fe608060405234801561001057600080fd5b50600436106102405760003560e01c80639a4575b911610145578063c4bffe2b116100bd578063dfadfa351161008c578063e8a1da1711610071578063e8a1da1714610700578063f2fde38b14610713578063fbf84dd71461072657600080fd5b8063dfadfa351461063c578063e0351e13146106da57600080fd5b8063c4bffe2b146105db578063c75eea9c146105f0578063cf7401f314610603578063dc0bd9711461061657600080fd5b8063acfecf9111610114578063b0f479a1116100f9578063b0f479a114610597578063b7946580146105b5578063c0d78655146105c857600080fd5b8063acfecf9114610515578063af58d59f1461052857600080fd5b80639a4575b9146104b85780639fdf13ff146104d8578063a42a7b8b146104e0578063a7cd63b71461050057600080fd5b806354c8a4f3116101d85780636d3d1a58116101a75780637d54534e1161018c5780637d54534e146104745780638926f54f146104875780638da5cb5b1461049a57600080fd5b80636d3d1a581461044e57806379ba50971461046c57600080fd5b806354c8a4f3146103c55780636155cda0146103d857806362ddd3c4146103ff5780636b716b0d1461041257600080fd5b8063240028e811610214578063240028e81461031257806324f65ee71461035f57806339077537146103905780634c5ef0ed146103b257600080fd5b806241d3c11461024557806301ffc9a71461025a578063181f5a771461028257806321df0da7146102cb575b600080fd5b610258610253366004613577565b61074d565b005b61026d6102683660046135ec565b6108ea565b60405190151581526020015b60405180910390f35b6102be6040518060400160405280601381526020017f55534443546f6b656e506f6f6c20312e352e310000000000000000000000000081525081565b6040516102799190613692565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610279565b61026d6103203660046136c7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610279565b6103a361039e3660046136e4565b6109cf565b60405190518152602001610279565b61026d6103c0366004613736565b610bb4565b6102586103d3366004613807565b610bfe565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b61025861040d366004613736565b610c79565b6104397f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610279565b60095473ffffffffffffffffffffffffffffffffffffffff166102ed565b610258610d11565b6102586104823660046136c7565b610ddf565b61026d610495366004613873565b610e60565b60015473ffffffffffffffffffffffffffffffffffffffff166102ed565b6104cb6104c6366004613890565b610e77565b60405161027991906138cb565b610439600081565b6104f36104ee366004613873565b6111b7565b6040516102799190613922565b610508611322565b60405161027991906139a4565b610258610523366004613736565b611333565b61053b610536366004613873565b61144b565b604051610279919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60045473ffffffffffffffffffffffffffffffffffffffff166102ed565b6102be6105c3366004613873565b611520565b6102586105d63660046136c7565b6115d0565b6105e36116a4565b60405161027991906139fe565b61053b6105fe366004613873565b61175c565b610258610611366004613b8b565b61182e565b7f00000000000000000000000000000000000000000000000000000000000000006102ed565b6106b061064a366004613873565b60408051606080820183526000808352602080840182905292840181905267ffffffffffffffff949094168452600a82529282902082519384018352805484526001015463ffffffff811691840191909152640100000000900460ff1615159082015290565b604080518251815260208084015163ffffffff169082015291810151151590820152606001610279565b7f000000000000000000000000000000000000000000000000000000000000000061026d565b61025861070e366004613807565b6118b2565b6102586107213660046136c7565b611dc4565b6102ed7f000000000000000000000000000000000000000000000000000000000000000081565b610755611dd8565b60005b818110156108ac57600083838381811061077457610774613bd2565b90506080020180360381019061078a9190613c15565b805190915015806107a75750604081015167ffffffffffffffff16155b1561081657604080517fa087bd2900000000000000000000000000000000000000000000000000000000815282516004820152602083015163ffffffff1660248201529082015167ffffffffffffffff1660448201526060820151151560648201526084015b60405180910390fd5b60408051606080820183528351825260208085015163ffffffff9081168285019081529286015115158486019081529585015167ffffffffffffffff166000908152600a90925293902091518255516001918201805494511515640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000909516919093161792909217905501610758565b507f1889010d2535a0ab1643678d1da87fbbe8b87b2f585b47ddb72ec622aef9ee5682826040516108de929190613c8f565b60405180910390a15050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167faff2afbf00000000000000000000000000000000000000000000000000000000148061097d57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e64dd2900000000000000000000000000000000000000000000000000000000145b806109c957507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6040805160208101909152600081526109e782611e2b565b60006109f660c0840184613d16565b810190610a039190613d7b565b90506000610a1460e0850185613d16565b810190610a219190613e48565b9050610a3181600001518361204f565b805160208201516040517f57ecfd2800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016926357ecfd2892610aa892600401613ed9565b6020604051808303816000875af1158015610ac7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aeb9190613efe565b610b21576040517fbf969f2200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b3160608501604086016136c7565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f9d228d69b5fdb8d273a2336f8fb8612d039631024ea9bf09c424a9503aa078f08660600135604051610b9391815260200190565b60405180910390a35050604080516020810190915260609092013582525090565b6000610bf68383604051610bc9929190613f1b565b604080519182900390912067ffffffffffffffff8716600090815260076020529190912060050190612200565b949350505050565b610c06611dd8565b610c738484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060408051602080880282810182019093528782529093508792508691829185019084908082843760009201919091525061221b92505050565b50505050565b610c81611dd8565b610c8a83610e60565b610ccc576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b610d0c8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123d192505050565b505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d62576040517f02b543c600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000008082163390811790935560008054909116815560405173ffffffffffffffffffffffffffffffffffffffff909216929183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610de7611dd8565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d091749060200160405180910390a150565b60006109c9600567ffffffffffffffff8416612200565b6040805180820190915260608082526020820152610e94826124cb565b6000600a81610ea96040860160208701613873565b67ffffffffffffffff168152602080820192909252604090810160002081516060810183528154815260019091015463ffffffff81169382019390935264010000000090920460ff161515908201819052909150610f5057610f116040840160208501613873565b6040517fd201c48a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b610f5a8380613d16565b9050602014610fa157610f6d8380613d16565b6040517fa3c8cf0900000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b6000610fad8480613d16565b810190610fba9190613f88565b602083015183516040517ff856ddb60000000000000000000000000000000000000000000000000000000081526060880135600482015263ffffffff90921660248301526044820183905273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116606484015260848301919091529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f856ddb69060a4016020604051808303816000875af115801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190613fa1565b6040516060870135815290915033907f696de425f79f4a40bc6d2122ca50507f0efbeabbff86a84871b7196ab8ea8df79060200160405180910390a2604051806040016040528061111c8760200160208101906105c39190613873565b815260408051808201825267ffffffffffffffff851680825263ffffffff7f00000000000000000000000000000000000000000000000000000000000000008116602093840190815284518085019390935251169281019290925290910190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905295945050505050565b67ffffffffffffffff81166000908152600760205260408120606091906111e090600501612657565b90506000815167ffffffffffffffff8111156111fe576111fe613a40565b60405190808252806020026020018201604052801561123157816020015b606081526020019060019003908161121c5790505b50905060005b825181101561131a576008600084838151811061125657611256613bd2565b60200260200101518152602001908152602001600020805461127790613fbe565b80601f01602080910402602001604051908101604052809291908181526020018280546112a390613fbe565b80156112f05780601f106112c5576101008083540402835291602001916112f0565b820191906000526020600020905b8154815290600101906020018083116112d357829003601f168201915b505050505082828151811061130757611307613bd2565b6020908102919091010152600101611237565b509392505050565b606061132e6002612657565b905090565b61133b611dd8565b61134483610e60565b611386576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b6113c68282604051611399929190613f1b565b604080519182900390912067ffffffffffffffff8616600090815260076020529190912060050190612664565b611402578282826040517f74f23c7c00000000000000000000000000000000000000000000000000000000815260040161080d93929190614011565b8267ffffffffffffffff167f52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76838360405161143e929190613f74565b60405180910390a2505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845260028201546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260039091015480841660608301529190910490911660808201526109c990612670565b67ffffffffffffffff8116600090815260076020526040902060040180546060919061154b90613fbe565b80601f016020809104026020016040519081016040528092919081815260200182805461157790613fbe565b80156115c45780601f10611599576101008083540402835291602001916115c4565b820191906000526020600020905b8154815290600101906020018083116115a757829003601f168201915b50505050509050919050565b6115d8611dd8565b73ffffffffffffffffffffffffffffffffffffffff8116611625576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117909355604080519190921680825260208201939093527f02dc5c233404867c793b749c6d644beb2277536d18a7e7974d3f238e4c6f168491016108de565b606060006116b26005612657565b90506000815167ffffffffffffffff8111156116d0576116d0613a40565b6040519080825280602002602001820160405280156116f9578160200160208202803683370190505b50905060005b82518110156117555782818151811061171a5761171a613bd2565b602002602001015182828151811061173457611734613bd2565b67ffffffffffffffff909216602092830291909101909101526001016116ff565b5092915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915267ffffffffffffffff8216600090815260076020908152604091829020825160a08101845281546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff16958401959095527401000000000000000000000000000000000000000090910460ff1615159482019490945260019091015480841660608301529190910490911660808201526109c990612670565b60095473ffffffffffffffffffffffffffffffffffffffff16331480159061186e575060015473ffffffffffffffffffffffffffffffffffffffff163314155b156118a7576040517f8e4a23d600000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b610d0c838383612722565b6118ba611dd8565b60005b83811015611aa75760008585838181106118d9576118d9613bd2565b90506020020160208101906118ee9190613873565b9050611905600567ffffffffffffffff8316612664565b611947576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b67ffffffffffffffff8116600090815260076020526040812061196c90600501612657565b905060005b81518110156119d8576119cf82828151811061198f5761198f613bd2565b6020026020010151600760008667ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060050161266490919063ffffffff16565b50600101611971565b5067ffffffffffffffff8216600090815260076020526040812080547fffffffffffffffffffffff00000000000000000000000000000000000000000090811682556001820183905560028201805490911690556003810182905590611a41600483018261350a565b6005820160008181611a538282613544565b505060405167ffffffffffffffff871681527f5204aec90a3c794d8e90fded8b46ae9c7c552803e7e832e0c1d358396d85991694506020019250611a95915050565b60405180910390a150506001016118bd565b5060005b81811015611dbd576000838383818110611ac757611ac7613bd2565b9050602002810190611ad99190614035565b611ae290614112565b9050611af38160600151600061280c565b611b028160800151600061280c565b806040015151600003611b41576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051611b599060059067ffffffffffffffff16612949565b611b9e5780516040517f1d5ad3c500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161080d565b805167ffffffffffffffff16600090815260076020908152604091829020825160a08082018552606080870180518601516fffffffffffffffffffffffffffffffff90811680865263ffffffff42168689018190528351511515878b0181905284518a0151841686890181905294518b0151841660809889018190528954740100000000000000000000000000000000000000009283027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff7001000000000000000000000000000000008087027fffffffffffffffffffffffff000000000000000000000000000000000000000094851690981788178216929092178d5592810290971760018c01558c519889018d52898e0180518d01518716808b528a8e019590955280515115158a8f018190528151909d01518716988a01899052518d0151909516979098018790526002890180549a909102999093161717909416959095179092559092029091176003820155908201516004820190611d21908261421a565b5060005b826020015151811015611d6557611d5d836000015184602001518381518110611d5057611d50613bd2565b60200260200101516123d1565b600101611d25565b507f8d340f17e19058004c20453540862a9c62778504476f6756755cb33bcd6c38c28260000151836040015184606001518560800151604051611dab9493929190614334565b60405180910390a15050600101611aab565b5050505050565b611dcc611dd8565b611dd581612955565b50565b60015473ffffffffffffffffffffffffffffffffffffffff163314611e29576040517f2b5c74de00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b611e3e61032060a08301608084016136c7565b611e9d57611e5260a08201608083016136c7565b6040517f961c9a4f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161080d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb611ee96040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa158015611f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7e9190613efe565b15611fb5576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611fcd611fc86040830160208401613873565b612a19565b611fed611fe06040830160208401613873565b6103c060a0840184613d16565b61203257611ffe60a0820182613d16565b6040517f24eb47e500000000000000000000000000000000000000000000000000000000815260040161080d929190613f74565b611dd56120456040830160208401613873565b8260600135612b3f565b600482015163ffffffff81161561209a576040517f68d2f8d600000000000000000000000000000000000000000000000000000000815263ffffffff8216600482015260240161080d565b6008830151600c8401516014850151602085015163ffffffff8085169116146121055760208501516040517fe366a11700000000000000000000000000000000000000000000000000000000815263ffffffff9182166004820152908416602482015260440161080d565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168263ffffffff161461219a576040517f77e4802600000000000000000000000000000000000000000000000000000000815263ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528316602482015260440161080d565b845167ffffffffffffffff8281169116146121f85784516040517ff917ffea00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9182166004820152908216602482015260440161080d565b505050505050565b600081815260018301602052604081205415155b9392505050565b7f0000000000000000000000000000000000000000000000000000000000000000612272576040517f35f4a7b300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b825181101561230857600083828151811061229257612292613bd2565b602002602001015190506122b0816002612b8690919063ffffffff16565b156122ff5760405173ffffffffffffffffffffffffffffffffffffffff821681527f800671136ab6cfee9fbe5ed1fb7ca417811aca3cf864800d127b927adedf75669060200160405180910390a15b50600101612275565b5060005b8151811015610d0c57600082828151811061232957612329613bd2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361236d57506123c9565b612378600282612ba8565b156123c75760405173ffffffffffffffffffffffffffffffffffffffff821681527f2640d4d76caf8bf478aabfa982fa4e1c4eb71a37f93cd15e80dbc657911546d89060200160405180910390a15b505b60010161230c565b805160000361240c576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160208083019190912067ffffffffffffffff841660009081526007909252604090912061243e9060050182612949565b6124785782826040517f393b8ad200000000000000000000000000000000000000000000000000000000815260040161080d9291906143cd565b6000818152600860205260409020612490838261421a565b508267ffffffffffffffff167f7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea8360405161143e9190613692565b6124de61032060a08301608084016136c7565b6124f257611e5260a08201608083016136c7565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016632cbc26bb61253e6040840160208501613873565b60405160e083901b7fffffffff0000000000000000000000000000000000000000000000000000000016815260809190911b77ffffffffffffffff00000000000000000000000000000000166004820152602401602060405180830381865afa1580156125af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d39190613efe565b1561260a576040517f53ad11d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61262261261d60608301604084016136c7565b612bca565b61263a6126356040830160208401613873565b612c49565b611dd561264d6040830160208401613873565b8260600135612d97565b6060600061221483612ddb565b60006122148383612e36565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526126fe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff16426126e2919061441f565b85608001516fffffffffffffffffffffffffffffffff16612f29565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b61272b83610e60565b61276d576040517f1e670e4b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8416600482015260240161080d565b61277882600061280c565b67ffffffffffffffff8316600090815260076020526040902061279b9083612f51565b6127a681600061280c565b67ffffffffffffffff831660009081526007602052604090206127cc9060020182612f51565b7f0350d63aa5f270e01729d00d627eeb8f3429772b1818c016c66a588a864f912b8383836040516127ff93929190614432565b60405180910390a1505050565b8151156128d75781602001516fffffffffffffffffffffffffffffffff1682604001516fffffffffffffffffffffffffffffffff16101580612862575060408201516fffffffffffffffffffffffffffffffff16155b1561289b57816040517f8020d12400000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b80156128d3576040517f433fc33d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b60408201516fffffffffffffffffffffffffffffffff16151580612910575060208201516fffffffffffffffffffffffffffffffff1615155b156128d357816040517fd68af9cc00000000000000000000000000000000000000000000000000000000815260040161080d91906144b5565b600061221483836130f3565b3373ffffffffffffffffffffffffffffffffffffffff8216036129a4576040517fdad89dca00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b612a2281610e60565b612a64576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517f83826b2b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925233602483015273ffffffffffffffffffffffffffffffffffffffff16906383826b2b90604401602060405180830381865afa158015612ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b079190613efe565b611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390600201827f0000000000000000000000000000000000000000000000000000000000000000613142565b60006122148373ffffffffffffffffffffffffffffffffffffffff8416612e36565b60006122148373ffffffffffffffffffffffffffffffffffffffff84166130f3565b7f000000000000000000000000000000000000000000000000000000000000000015611dd557612bfb6002826134c5565b611dd5576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260240161080d565b612c5281610e60565b612c94576040517fa9902c7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161080d565b600480546040517fa8d87a3b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84169281019290925273ffffffffffffffffffffffffffffffffffffffff169063a8d87a3b90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d3191906144f1565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611dd5576040517f728fe07b00000000000000000000000000000000000000000000000000000000815233600482015260240161080d565b67ffffffffffffffff821660009081526007602052604090206128d390827f0000000000000000000000000000000000000000000000000000000000000000613142565b6060816000018054806020026020016040519081016040528092919081815260200182805480156115c457602002820191906000526020600020905b815481526020019060010190808311612e175750505050509050919050565b60008181526001830160205260408120548015612f1f576000612e5a60018361441f565b8554909150600090612e6e9060019061441f565b9050808214612ed3576000866000018281548110612e8e57612e8e613bd2565b9060005260206000200154905080876000018481548110612eb157612eb1613bd2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ee457612ee461450e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506109c9565b60009150506109c9565b6000612f4885612f39848661453d565b612f439087614554565b6134f4565b95945050505050565b8154600090612f7a90700100000000000000000000000000000000900463ffffffff164261441f565b9050801561301c5760018301548354612fc2916fffffffffffffffffffffffffffffffff80821692811691859170010000000000000000000000000000000090910416612f29565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b60208201518354613042916fffffffffffffffffffffffffffffffff90811691166134f4565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906127ff9084906144b5565b600081815260018301602052604081205461313a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556109c9565b5060006109c9565b825474010000000000000000000000000000000000000000900460ff161580613169575081155b1561317357505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906131b990700100000000000000000000000000000000900463ffffffff164261441f565b9050801561327957818311156131fb576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546132359083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16612f29565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156133305773ffffffffffffffffffffffffffffffffffffffff84166132d8576040517ff94ebcd1000000000000000000000000000000000000000000000000000000008152600481018390526024810186905260440161080d565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff8516604482015260640161080d565b848310156134435760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290613374908261441f565b61337e878a61441f565b6133889190614554565b6133929190614567565b905073ffffffffffffffffffffffffffffffffffffffff86166133eb576040517f15279c08000000000000000000000000000000000000000000000000000000008152600481018290526024810186905260440161080d565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff8716604482015260640161080d565b61344d858461441f565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515612214565b60008183106135035781612214565b5090919050565b50805461351690613fbe565b6000825580601f10613526575050565b601f016020900490600052602060002090810190611dd5919061355e565b5080546000825590600052602060002090810190611dd591905b5b80821115613573576000815560010161355f565b5090565b6000806020838503121561358a57600080fd5b823567ffffffffffffffff808211156135a257600080fd5b818501915085601f8301126135b657600080fd5b8135818111156135c557600080fd5b8660208260071b85010111156135da57600080fd5b60209290920196919550909350505050565b6000602082840312156135fe57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461221457600080fd5b6000815180845260005b8181101561365457602081850181015186830182015201613638565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612214602083018461362e565b73ffffffffffffffffffffffffffffffffffffffff81168114611dd557600080fd5b6000602082840312156136d957600080fd5b8135612214816136a5565b6000602082840312156136f657600080fd5b813567ffffffffffffffff81111561370d57600080fd5b8201610100818503121561221457600080fd5b67ffffffffffffffff81168114611dd557600080fd5b60008060006040848603121561374b57600080fd5b833561375681613720565b9250602084013567ffffffffffffffff8082111561377357600080fd5b818601915086601f83011261378757600080fd5b81358181111561379657600080fd5b8760208285010111156137a857600080fd5b6020830194508093505050509250925092565b60008083601f8401126137cd57600080fd5b50813567ffffffffffffffff8111156137e557600080fd5b6020830191508360208260051b850101111561380057600080fd5b9250929050565b6000806000806040858703121561381d57600080fd5b843567ffffffffffffffff8082111561383557600080fd5b613841888389016137bb565b9096509450602087013591508082111561385a57600080fd5b50613867878288016137bb565b95989497509550505050565b60006020828403121561388557600080fd5b813561221481613720565b6000602082840312156138a257600080fd5b813567ffffffffffffffff8111156138b957600080fd5b820160a0818503121561221457600080fd5b6020815260008251604060208401526138e7606084018261362e565b905060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848303016040850152612f48828261362e565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015613997577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261398585835161362e565b9450928501929085019060010161394b565b5092979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139c0565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156139f257835167ffffffffffffffff1683529284019291840191600101613a1a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613a9257613a92613a40565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613adf57613adf613a40565b604052919050565b8015158114611dd557600080fd5b80356fffffffffffffffffffffffffffffffff81168114613b1557600080fd5b919050565b600060608284031215613b2c57600080fd5b6040516060810181811067ffffffffffffffff82111715613b4f57613b4f613a40565b6040529050808235613b6081613ae7565b8152613b6e60208401613af5565b6020820152613b7f60408401613af5565b60408201525092915050565b600080600060e08486031215613ba057600080fd5b8335613bab81613720565b9250613bba8560208601613b1a565b9150613bc98560808601613b1a565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b803563ffffffff81168114613b1557600080fd5b600060808284031215613c2757600080fd5b6040516080810181811067ffffffffffffffff82111715613c4a57613c4a613a40565b60405282358152613c5d60208401613c01565b60208201526040830135613c7081613720565b60408201526060830135613c8381613ae7565b60608201529392505050565b6020808252818101839052600090604080840186845b87811015613d09578135835263ffffffff613cc1868401613c01565b168584015283820135613cd381613720565b67ffffffffffffffff1683850152606082810135613cf081613ae7565b1515908401526080928301929190910190600101613ca5565b5090979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613d4b57600080fd5b83018035915067ffffffffffffffff821115613d6657600080fd5b60200191503681900382131561380057600080fd5b600060408284031215613d8d57600080fd5b613d95613a6f565b8235613da081613720565b8152613dae60208401613c01565b60208201529392505050565b600082601f830112613dcb57600080fd5b813567ffffffffffffffff811115613de557613de5613a40565b613e1660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613a98565b818152846020838601011115613e2b57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215613e5a57600080fd5b813567ffffffffffffffff80821115613e7257600080fd5b9083019060408286031215613e8657600080fd5b613e8e613a6f565b823582811115613e9d57600080fd5b613ea987828601613dba565b825250602083013582811115613ebe57600080fd5b613eca87828601613dba565b60208301525095945050505050565b604081526000613eec604083018561362e565b8281036020840152612f48818561362e565b600060208284031215613f1057600080fd5b815161221481613ae7565b8183823760009101908152919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000610bf6602083018486613f2b565b600060208284031215613f9a57600080fd5b5035919050565b600060208284031215613fb357600080fd5b815161221481613720565b600181811c90821680613fd257607f821691505b60208210810361400b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b67ffffffffffffffff84168152604060208201526000612f48604083018486613f2b565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee183360301811261406957600080fd5b9190910192915050565b600082601f83011261408457600080fd5b8135602067ffffffffffffffff808311156140a1576140a1613a40565b8260051b6140b0838201613a98565b93845285810183019383810190888611156140ca57600080fd5b84880192505b85831015614106578235848111156140e85760008081fd5b6140f68a87838c0101613dba565b83525091840191908401906140d0565b98975050505050505050565b6000610120823603121561412557600080fd5b60405160a0810167ffffffffffffffff828210818311171561414957614149613a40565b816040528435915061415a82613720565b9082526020840135908082111561417057600080fd5b61417c36838701614073565b6020840152604085013591508082111561419557600080fd5b506141a236828601613dba565b6040830152506141b53660608501613b1a565b60608201526141c73660c08501613b1a565b608082015292915050565b601f821115610d0c576000816000526020600020601f850160051c810160208610156141fb5750805b601f850160051c820191505b818110156121f857828155600101614207565b815167ffffffffffffffff81111561423457614234613a40565b614248816142428454613fbe565b846141d2565b602080601f83116001811461429b57600084156142655750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556121f8565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142e8578886015182559484019460019091019084016142c9565b508582101561432457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600061010067ffffffffffffffff871683528060208401526143588184018761362e565b8551151560408581019190915260208701516fffffffffffffffffffffffffffffffff90811660608701529087015116608085015291506143969050565b8251151560a083015260208301516fffffffffffffffffffffffffffffffff90811660c084015260408401511660e0830152612f48565b67ffffffffffffffff83168152604060208201526000610bf6604083018461362e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156109c9576109c96143f0565b67ffffffffffffffff8416815260e0810161447e60208301858051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b82511515608083015260208301516fffffffffffffffffffffffffffffffff90811660a084015260408401511660c0830152610bf6565b606081016109c982848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006020828403121561450357600080fd5b8151612214816136a5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b80820281158282048414176109c9576109c96143f0565b808201808211156109c9576109c96143f0565b60008261459d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea164736f6c6343000818000a", } var USDCTokenPoolABI = USDCTokenPoolMetaData.ABI @@ -389,26 +388,26 @@ func (_USDCTokenPool *USDCTokenPoolCallerSession) GetRateLimitAdmin() (common.Ad return _USDCTokenPool.Contract.GetRateLimitAdmin(&_USDCTokenPool.CallOpts) } -func (_USDCTokenPool *USDCTokenPoolCaller) GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { +func (_USDCTokenPool *USDCTokenPoolCaller) GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) { var out []interface{} - err := _USDCTokenPool.contract.Call(opts, &out, "getRemotePool", remoteChainSelector) + err := _USDCTokenPool.contract.Call(opts, &out, "getRemotePools", remoteChainSelector) if err != nil { - return *new([]byte), err + return *new([][]byte), err } - out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) return out0, err } -func (_USDCTokenPool *USDCTokenPoolSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _USDCTokenPool.Contract.GetRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector) +func (_USDCTokenPool *USDCTokenPoolSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _USDCTokenPool.Contract.GetRemotePools(&_USDCTokenPool.CallOpts, remoteChainSelector) } -func (_USDCTokenPool *USDCTokenPoolCallerSession) GetRemotePool(remoteChainSelector uint64) ([]byte, error) { - return _USDCTokenPool.Contract.GetRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector) +func (_USDCTokenPool *USDCTokenPoolCallerSession) GetRemotePools(remoteChainSelector uint64) ([][]byte, error) { + return _USDCTokenPool.Contract.GetRemotePools(&_USDCTokenPool.CallOpts, remoteChainSelector) } func (_USDCTokenPool *USDCTokenPoolCaller) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) { @@ -521,6 +520,28 @@ func (_USDCTokenPool *USDCTokenPoolCallerSession) GetToken() (common.Address, er return _USDCTokenPool.Contract.GetToken(&_USDCTokenPool.CallOpts) } +func (_USDCTokenPool *USDCTokenPoolCaller) GetTokenDecimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _USDCTokenPool.contract.Call(opts, &out, "getTokenDecimals") + + if err != nil { + return *new(uint8), err + } + + out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8) + + return out0, err + +} + +func (_USDCTokenPool *USDCTokenPoolSession) GetTokenDecimals() (uint8, error) { + return _USDCTokenPool.Contract.GetTokenDecimals(&_USDCTokenPool.CallOpts) +} + +func (_USDCTokenPool *USDCTokenPoolCallerSession) GetTokenDecimals() (uint8, error) { + return _USDCTokenPool.Contract.GetTokenDecimals(&_USDCTokenPool.CallOpts) +} + func (_USDCTokenPool *USDCTokenPoolCaller) ILocalDomainIdentifier(opts *bind.CallOpts) (uint32, error) { var out []interface{} err := _USDCTokenPool.contract.Call(opts, &out, "i_localDomainIdentifier") @@ -587,6 +608,28 @@ func (_USDCTokenPool *USDCTokenPoolCallerSession) ITokenMessenger() (common.Addr return _USDCTokenPool.Contract.ITokenMessenger(&_USDCTokenPool.CallOpts) } +func (_USDCTokenPool *USDCTokenPoolCaller) IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + var out []interface{} + err := _USDCTokenPool.contract.Call(opts, &out, "isRemotePool", remoteChainSelector, remotePoolAddress) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_USDCTokenPool *USDCTokenPoolSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _USDCTokenPool.Contract.IsRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + +func (_USDCTokenPool *USDCTokenPoolCallerSession) IsRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) { + return _USDCTokenPool.Contract.IsRemotePool(&_USDCTokenPool.CallOpts, remoteChainSelector, remotePoolAddress) +} + func (_USDCTokenPool *USDCTokenPoolCaller) IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) { var out []interface{} err := _USDCTokenPool.contract.Call(opts, &out, "isSupportedChain", remoteChainSelector) @@ -709,6 +752,18 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) AcceptOwnership() (*types. return _USDCTokenPool.Contract.AcceptOwnership(&_USDCTokenPool.TransactOpts) } +func (_USDCTokenPool *USDCTokenPoolTransactor) AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.contract.Transact(opts, "addRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_USDCTokenPool *USDCTokenPoolSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.Contract.AddRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_USDCTokenPool *USDCTokenPoolTransactorSession) AddRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.Contract.AddRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_USDCTokenPool *USDCTokenPoolTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "applyAllowListUpdates", removes, adds) } @@ -721,16 +776,16 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) ApplyAllowListUpdates(remo return _USDCTokenPool.Contract.ApplyAllowListUpdates(&_USDCTokenPool.TransactOpts, removes, adds) } -func (_USDCTokenPool *USDCTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _USDCTokenPool.contract.Transact(opts, "applyChainUpdates", chains) +func (_USDCTokenPool *USDCTokenPoolTransactor) ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _USDCTokenPool.contract.Transact(opts, "applyChainUpdates", remoteChainSelectorsToRemove, chainsToAdd) } -func (_USDCTokenPool *USDCTokenPoolSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, chains) +func (_USDCTokenPool *USDCTokenPoolSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } -func (_USDCTokenPool *USDCTokenPoolTransactorSession) ApplyChainUpdates(chains []TokenPoolChainUpdate) (*types.Transaction, error) { - return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, chains) +func (_USDCTokenPool *USDCTokenPoolTransactorSession) ApplyChainUpdates(remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) { + return _USDCTokenPool.Contract.ApplyChainUpdates(&_USDCTokenPool.TransactOpts, remoteChainSelectorsToRemove, chainsToAdd) } func (_USDCTokenPool *USDCTokenPoolTransactor) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) { @@ -757,6 +812,18 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) ReleaseOrMint(releaseOrMin return _USDCTokenPool.Contract.ReleaseOrMint(&_USDCTokenPool.TransactOpts, releaseOrMintIn) } +func (_USDCTokenPool *USDCTokenPoolTransactor) RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.contract.Transact(opts, "removeRemotePool", remoteChainSelector, remotePoolAddress) +} + +func (_USDCTokenPool *USDCTokenPoolSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.Contract.RemoveRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + +func (_USDCTokenPool *USDCTokenPoolTransactorSession) RemoveRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { + return _USDCTokenPool.Contract.RemoveRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) +} + func (_USDCTokenPool *USDCTokenPoolTransactor) SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "setChainRateLimiterConfig", remoteChainSelector, outboundConfig, inboundConfig) } @@ -793,18 +860,6 @@ func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetRateLimitAdmin(rateLimi return _USDCTokenPool.Contract.SetRateLimitAdmin(&_USDCTokenPool.TransactOpts, rateLimitAdmin) } -func (_USDCTokenPool *USDCTokenPoolTransactor) SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.contract.Transact(opts, "setRemotePool", remoteChainSelector, remotePoolAddress) -} - -func (_USDCTokenPool *USDCTokenPoolSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.Contract.SetRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - -func (_USDCTokenPool *USDCTokenPoolTransactorSession) SetRemotePool(remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) { - return _USDCTokenPool.Contract.SetRemotePool(&_USDCTokenPool.TransactOpts, remoteChainSelector, remotePoolAddress) -} - func (_USDCTokenPool *USDCTokenPoolTransactor) SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) { return _USDCTokenPool.contract.Transact(opts, "setRouter", newRouter) } @@ -2435,6 +2490,123 @@ func (_USDCTokenPool *USDCTokenPoolFilterer) ParseOwnershipTransferred(log types return event, nil } +type USDCTokenPoolRateLimitAdminSetIterator struct { + Event *USDCTokenPoolRateLimitAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *USDCTokenPoolRateLimitAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(USDCTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(USDCTokenPoolRateLimitAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *USDCTokenPoolRateLimitAdminSetIterator) Error() error { + return it.fail +} + +func (it *USDCTokenPoolRateLimitAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type USDCTokenPoolRateLimitAdminSet struct { + RateLimitAdmin common.Address + Raw types.Log +} + +func (_USDCTokenPool *USDCTokenPoolFilterer) FilterRateLimitAdminSet(opts *bind.FilterOpts) (*USDCTokenPoolRateLimitAdminSetIterator, error) { + + logs, sub, err := _USDCTokenPool.contract.FilterLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return &USDCTokenPoolRateLimitAdminSetIterator{contract: _USDCTokenPool.contract, event: "RateLimitAdminSet", logs: logs, sub: sub}, nil +} + +func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRateLimitAdminSet) (event.Subscription, error) { + + logs, sub, err := _USDCTokenPool.contract.WatchLogs(opts, "RateLimitAdminSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(USDCTokenPoolRateLimitAdminSet) + if err := _USDCTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_USDCTokenPool *USDCTokenPoolFilterer) ParseRateLimitAdminSet(log types.Log) (*USDCTokenPoolRateLimitAdminSet, error) { + event := new(USDCTokenPoolRateLimitAdminSet) + if err := _USDCTokenPool.contract.UnpackLog(event, "RateLimitAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type USDCTokenPoolReleasedIterator struct { Event *USDCTokenPoolReleased @@ -2572,8 +2744,136 @@ func (_USDCTokenPool *USDCTokenPoolFilterer) ParseReleased(log types.Log) (*USDC return event, nil } -type USDCTokenPoolRemotePoolSetIterator struct { - Event *USDCTokenPoolRemotePoolSet +type USDCTokenPoolRemotePoolAddedIterator struct { + Event *USDCTokenPoolRemotePoolAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *USDCTokenPoolRemotePoolAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(USDCTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(USDCTokenPoolRemotePoolAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *USDCTokenPoolRemotePoolAddedIterator) Error() error { + return it.fail +} + +func (it *USDCTokenPoolRemotePoolAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type USDCTokenPoolRemotePoolAdded struct { + RemoteChainSelector uint64 + RemotePoolAddress []byte + Raw types.Log +} + +func (_USDCTokenPool *USDCTokenPoolFilterer) FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolAddedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _USDCTokenPool.contract.FilterLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &USDCTokenPoolRemotePoolAddedIterator{contract: _USDCTokenPool.contract, event: "RemotePoolAdded", logs: logs, sub: sub}, nil +} + +func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _USDCTokenPool.contract.WatchLogs(opts, "RemotePoolAdded", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(USDCTokenPoolRemotePoolAdded) + if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_USDCTokenPool *USDCTokenPoolFilterer) ParseRemotePoolAdded(log types.Log) (*USDCTokenPoolRemotePoolAdded, error) { + event := new(USDCTokenPoolRemotePoolAdded) + if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type USDCTokenPoolRemotePoolRemovedIterator struct { + Event *USDCTokenPoolRemotePoolRemoved contract *bind.BoundContract event string @@ -2584,7 +2884,7 @@ type USDCTokenPoolRemotePoolSetIterator struct { fail error } -func (it *USDCTokenPoolRemotePoolSetIterator) Next() bool { +func (it *USDCTokenPoolRemotePoolRemovedIterator) Next() bool { if it.fail != nil { return false @@ -2593,7 +2893,7 @@ func (it *USDCTokenPoolRemotePoolSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(USDCTokenPoolRemotePoolSet) + it.Event = new(USDCTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2608,7 +2908,7 @@ func (it *USDCTokenPoolRemotePoolSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(USDCTokenPoolRemotePoolSet) + it.Event = new(USDCTokenPoolRemotePoolRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2623,44 +2923,43 @@ func (it *USDCTokenPoolRemotePoolSetIterator) Next() bool { } } -func (it *USDCTokenPoolRemotePoolSetIterator) Error() error { +func (it *USDCTokenPoolRemotePoolRemovedIterator) Error() error { return it.fail } -func (it *USDCTokenPoolRemotePoolSetIterator) Close() error { +func (it *USDCTokenPoolRemotePoolRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type USDCTokenPoolRemotePoolSet struct { +type USDCTokenPoolRemotePoolRemoved struct { RemoteChainSelector uint64 - PreviousPoolAddress []byte RemotePoolAddress []byte Raw types.Log } -func (_USDCTokenPool *USDCTokenPoolFilterer) FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolSetIterator, error) { +func (_USDCTokenPool *USDCTokenPoolFilterer) FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolRemovedIterator, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _USDCTokenPool.contract.FilterLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _USDCTokenPool.contract.FilterLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } - return &USDCTokenPoolRemotePoolSetIterator{contract: _USDCTokenPool.contract, event: "RemotePoolSet", logs: logs, sub: sub}, nil + return &USDCTokenPoolRemotePoolRemovedIterator{contract: _USDCTokenPool.contract, event: "RemotePoolRemoved", logs: logs, sub: sub}, nil } -func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) { +func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) { var remoteChainSelectorRule []interface{} for _, remoteChainSelectorItem := range remoteChainSelector { remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) } - logs, sub, err := _USDCTokenPool.contract.WatchLogs(opts, "RemotePoolSet", remoteChainSelectorRule) + logs, sub, err := _USDCTokenPool.contract.WatchLogs(opts, "RemotePoolRemoved", remoteChainSelectorRule) if err != nil { return nil, err } @@ -2670,8 +2969,8 @@ func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolSet(opts *bind.Watch select { case log := <-logs: - event := new(USDCTokenPoolRemotePoolSet) - if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { + event := new(USDCTokenPoolRemotePoolRemoved) + if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return err } event.Raw = log @@ -2692,9 +2991,9 @@ func (_USDCTokenPool *USDCTokenPoolFilterer) WatchRemotePoolSet(opts *bind.Watch }), nil } -func (_USDCTokenPool *USDCTokenPoolFilterer) ParseRemotePoolSet(log types.Log) (*USDCTokenPoolRemotePoolSet, error) { - event := new(USDCTokenPoolRemotePoolSet) - if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolSet", log); err != nil { +func (_USDCTokenPool *USDCTokenPoolFilterer) ParseRemotePoolRemoved(log types.Log) (*USDCTokenPoolRemotePoolRemoved, error) { + event := new(USDCTokenPoolRemotePoolRemoved) + if err := _USDCTokenPool.contract.UnpackLog(event, "RemotePoolRemoved", log); err != nil { return nil, err } event.Raw = log @@ -2964,10 +3263,14 @@ func (_USDCTokenPool *USDCTokenPool) ParseLog(log types.Log) (generated.AbigenLo return _USDCTokenPool.ParseOwnershipTransferRequested(log) case _USDCTokenPool.abi.Events["OwnershipTransferred"].ID: return _USDCTokenPool.ParseOwnershipTransferred(log) + case _USDCTokenPool.abi.Events["RateLimitAdminSet"].ID: + return _USDCTokenPool.ParseRateLimitAdminSet(log) case _USDCTokenPool.abi.Events["Released"].ID: return _USDCTokenPool.ParseReleased(log) - case _USDCTokenPool.abi.Events["RemotePoolSet"].ID: - return _USDCTokenPool.ParseRemotePoolSet(log) + case _USDCTokenPool.abi.Events["RemotePoolAdded"].ID: + return _USDCTokenPool.ParseRemotePoolAdded(log) + case _USDCTokenPool.abi.Events["RemotePoolRemoved"].ID: + return _USDCTokenPool.ParseRemotePoolRemoved(log) case _USDCTokenPool.abi.Events["RouterUpdated"].ID: return _USDCTokenPool.ParseRouterUpdated(log) case _USDCTokenPool.abi.Events["TokensConsumed"].ID: @@ -3030,12 +3333,20 @@ func (USDCTokenPoolOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (USDCTokenPoolRateLimitAdminSet) Topic() common.Hash { + return common.HexToHash("0x44676b5284b809a22248eba0da87391d79098be38bb03154be88a58bf4d09174") +} + func (USDCTokenPoolReleased) Topic() common.Hash { return common.HexToHash("0x2d87480f50083e2b2759522a8fdda59802650a8055e609a7772cf70c07748f52") } -func (USDCTokenPoolRemotePoolSet) Topic() common.Hash { - return common.HexToHash("0xdb4d6220746a38cbc5335f7e108f7de80f482f4d23350253dfd0917df75a14bf") +func (USDCTokenPoolRemotePoolAdded) Topic() common.Hash { + return common.HexToHash("0x7d628c9a1796743d365ab521a8b2a4686e419b3269919dc9145ea2ce853b54ea") +} + +func (USDCTokenPoolRemotePoolRemoved) Topic() common.Hash { + return common.HexToHash("0x52d00ee4d9bd51b40168f2afc5848837288ce258784ad914278791464b3f4d76") } func (USDCTokenPoolRouterUpdated) Topic() common.Hash { @@ -3065,7 +3376,7 @@ type USDCTokenPoolInterface interface { GetRateLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetRemotePool(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) + GetRemotePools(opts *bind.CallOpts, remoteChainSelector uint64) ([][]byte, error) GetRemoteToken(opts *bind.CallOpts, remoteChainSelector uint64) ([]byte, error) @@ -3077,12 +3388,16 @@ type USDCTokenPoolInterface interface { GetToken(opts *bind.CallOpts) (common.Address, error) + GetTokenDecimals(opts *bind.CallOpts) (uint8, error) + ILocalDomainIdentifier(opts *bind.CallOpts) (uint32, error) IMessageTransmitter(opts *bind.CallOpts) (common.Address, error) ITokenMessenger(opts *bind.CallOpts) (common.Address, error) + IsRemotePool(opts *bind.CallOpts, remoteChainSelector uint64, remotePoolAddress []byte) (bool, error) + IsSupportedChain(opts *bind.CallOpts, remoteChainSelector uint64) (bool, error) IsSupportedToken(opts *bind.CallOpts, token common.Address) (bool, error) @@ -3095,22 +3410,24 @@ type USDCTokenPoolInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + AddRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + ApplyAllowListUpdates(opts *bind.TransactOpts, removes []common.Address, adds []common.Address) (*types.Transaction, error) - ApplyChainUpdates(opts *bind.TransactOpts, chains []TokenPoolChainUpdate) (*types.Transaction, error) + ApplyChainUpdates(opts *bind.TransactOpts, remoteChainSelectorsToRemove []uint64, chainsToAdd []TokenPoolChainUpdate) (*types.Transaction, error) LockOrBurn(opts *bind.TransactOpts, lockOrBurnIn PoolLockOrBurnInV1) (*types.Transaction, error) ReleaseOrMint(opts *bind.TransactOpts, releaseOrMintIn PoolReleaseOrMintInV1) (*types.Transaction, error) + RemoveRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) + SetChainRateLimiterConfig(opts *bind.TransactOpts, remoteChainSelector uint64, outboundConfig RateLimiterConfig, inboundConfig RateLimiterConfig) (*types.Transaction, error) SetDomains(opts *bind.TransactOpts, domains []USDCTokenPoolDomainUpdate) (*types.Transaction, error) SetRateLimitAdmin(opts *bind.TransactOpts, rateLimitAdmin common.Address) (*types.Transaction, error) - SetRemotePool(opts *bind.TransactOpts, remoteChainSelector uint64, remotePoolAddress []byte) (*types.Transaction, error) - SetRouter(opts *bind.TransactOpts, newRouter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -3193,17 +3510,29 @@ type USDCTokenPoolInterface interface { ParseOwnershipTransferred(log types.Log) (*USDCTokenPoolOwnershipTransferred, error) + FilterRateLimitAdminSet(opts *bind.FilterOpts) (*USDCTokenPoolRateLimitAdminSetIterator, error) + + WatchRateLimitAdminSet(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRateLimitAdminSet) (event.Subscription, error) + + ParseRateLimitAdminSet(log types.Log) (*USDCTokenPoolRateLimitAdminSet, error) + FilterReleased(opts *bind.FilterOpts, sender []common.Address, recipient []common.Address) (*USDCTokenPoolReleasedIterator, error) WatchReleased(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolReleased, sender []common.Address, recipient []common.Address) (event.Subscription, error) ParseReleased(log types.Log) (*USDCTokenPoolReleased, error) - FilterRemotePoolSet(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolSetIterator, error) + FilterRemotePoolAdded(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolAddedIterator, error) + + WatchRemotePoolAdded(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolAdded, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRemotePoolAdded(log types.Log) (*USDCTokenPoolRemotePoolAdded, error) + + FilterRemotePoolRemoved(opts *bind.FilterOpts, remoteChainSelector []uint64) (*USDCTokenPoolRemotePoolRemovedIterator, error) - WatchRemotePoolSet(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolSet, remoteChainSelector []uint64) (event.Subscription, error) + WatchRemotePoolRemoved(opts *bind.WatchOpts, sink chan<- *USDCTokenPoolRemotePoolRemoved, remoteChainSelector []uint64) (event.Subscription, error) - ParseRemotePoolSet(log types.Log) (*USDCTokenPoolRemotePoolSet, error) + ParseRemotePoolRemoved(log types.Log) (*USDCTokenPoolRemotePoolRemoved, error) FilterRouterUpdated(opts *bind.FilterOpts) (*USDCTokenPoolRouterUpdatedIterator, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 258ae7a753..0399a3574b 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,9 +1,9 @@ GETH_VERSION: 1.13.8 -burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 1e60c28ad796a220a38043b369dec8d9bffe23e1c7d9895760e30672872afd06 -burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 3e8e3358f0bb520af069a7d37ea625940a88461a54418b1d5925eabced8c74df +burn_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin 642919607d5642aa98713b88f737c918487adba682535cf630b7c7d5fd80dc43 +burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin 054d95f302a142f7b64eea27237e0889bee6c9eb8a487579c7279c09646dc42b burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 717c079d5d13300cf3c3ee871c6e5bf9af904411f204fb081a9f3b263cca1391 burn_with_from_mint_rebasing_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintRebasingTokenPool/BurnWithFromMintRebasingTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintRebasingTokenPool/BurnWithFromMintRebasingTokenPool.bin ec9b95105a33de14b078c1261d9cd9d6f3011e940a819b52f11a963951d4bb89 -burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 734c2a0ea8f1224b5f01ed849410209e74b4e3427e8bfddb8ff5dd8ead5f2d8d +burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin c3f723e7f6394297c095a9d9696f1bceec4a2e85b5be2159f7a21d257eb6b480 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 1ed5c299f928529081dc01b7a46db2b5e6728001767863495a7675d8db99a9e2 ccip_encoding_utils: ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/ICCIPEncodingUtils/ICCIPEncodingUtils.bin 2e6fa009821d30a24efdc9f9d14b2269fb9a51cb7d536ea8b2d29d97dd8b591c ccip_home: ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.abi ../../../contracts/solc/v0.8.24/CCIPHome/CCIPHome.bin c570b86f8ae7697d3478e70625e06f0f682e75c1f0b7538f4b6f581b0d294b2b @@ -14,7 +14,7 @@ ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/Ether evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 503823a939ff99fe3bdaaef7a89cd4bbe475e260d3921335dbf9c80d4f584b76 -lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 +lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 1067f557abeb5570f1da7f050ea982ffad0f35dc064e668a8a0e6af128df490c lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 0a2661da24147160383ad61d56a258515d1cc07f5e0f471ec5cbb4bccaf82389 @@ -36,6 +36,6 @@ rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../con router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 8ea5d75dbc3f8afd90d22c4a665a94e02892259cd16520c1c6b4cf0dc80c9148 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 942be7d1681ac102e0615bee13f76838ebb0b261697cf1270d2bf82c12e57aeb -token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin 7c01fd89f5153baa4d7409d14beabb3f861abfbf8880d3c6d06802cc398570f9 -usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin 8e7eae4c7277ce4a0092cca815c046cc49094028c23d2d113de9335fa4358030 +token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin da86a1407f31134e7246bde63c80ce8c78ce7d7b44e267f3c1f6030441ff4252 +usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin b688126b13353f7aab7481f3f6b8f79cd2cace96be71eace70237d402823493a weth9: ../../../contracts/solc/v0.8.24/WETH9/WETH9.abi ../../../contracts/solc/v0.8.24/WETH9/WETH9.bin 2970d79a0ca6dd6279cde130de45e56c8790ed695eae477fb5ba4c1bb75b720d diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index fd48a3826f..d0f5951323 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -23,13 +23,9 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMintTokenPool.bin BurnMintTokenPool burn_mint_token_pool //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnFromMintTokenPool/BurnFromMintTokenPool.bin BurnFromMintTokenPool burn_from_mint_token_pool //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin BurnWithFromMintTokenPool burn_with_from_mint_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin BurnMintTokenPoolAndProxy burn_mint_token_pool_and_proxy -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin BurnWithFromMintTokenPoolAndProxy burn_with_from_mint_token_pool_and_proxy //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin LockReleaseTokenPool lock_release_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin LockReleaseTokenPoolAndProxy lock_release_token_pool_and_proxy //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin TokenPool token_pool //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin USDCTokenPool usdc_token_pool -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/BurnWithFromMintRebasingTokenPool/BurnWithFromMintRebasingTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintRebasingTokenPool/BurnWithFromMintRebasingTokenPool.bin BurnWithFromMintRebasingTokenPool burn_with_from_mint_rebasing_token_pool // Helpers //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin MockV3Aggregator mock_v3_aggregator_contract diff --git a/core/scripts/ccip/liquiditymanager/util.go b/core/scripts/ccip/liquiditymanager/util.go index 45aa69ddb8..d49b49f0ed 100644 --- a/core/scripts/ccip/liquiditymanager/util.go +++ b/core/scripts/ccip/liquiditymanager/util.go @@ -243,6 +243,7 @@ func deployTokenPoolAndRebalancer( transactor, client, tokenAddress, + 18, []common.Address{}, armProxyAddress, true, diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go index 0442f09c47..ee514c6b19 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go @@ -73,6 +73,8 @@ var ( SourceChainSelector = uint64(11787463284727550157) DestChainID = uint64(1337) DestChainSelector = uint64(3379446385462418246) + + TokenDecimals = uint8(18) ) // Backwards compat, in principle these statuses are version dependent @@ -785,6 +787,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh sourceUser, sourceChain, sourceLinkTokenAddress, + TokenDecimals, []common.Address{}, armProxySourceAddress, true, @@ -801,6 +804,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh sourceUser, sourceChain, sourceWeth9addr, + TokenDecimals, []common.Address{}, armProxySourceAddress, true, @@ -819,6 +823,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh destUser, destChain, destLinkTokenAddress, + TokenDecimals, []common.Address{}, armProxyDestAddress, true, @@ -848,6 +853,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh destUser, destChain, destWeth9addr, + TokenDecimals, []common.Address{}, armProxyDestAddress, true, @@ -882,11 +888,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = sourceLinkPool.ApplyChainUpdates( sourceUser, + []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: DestChainSelector, - RemotePoolAddress: abiEncodedDestLinkPool, + RemotePoolAddresses: [][]byte{abiEncodedDestLinkPool}, RemoteTokenAddress: abiEncodedDestLinkTokenAddress, - Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, @@ -907,11 +913,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = sourceWeth9Pool.ApplyChainUpdates( sourceUser, + []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: DestChainSelector, - RemotePoolAddress: abiEncodedDestWrappedPool, + RemotePoolAddresses: [][]byte{abiEncodedDestWrappedPool}, RemoteTokenAddress: abiEncodedDestWrappedTokenAddr, - Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, @@ -933,11 +939,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = destLinkPool.ApplyChainUpdates( destUser, + []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: SourceChainSelector, - RemotePoolAddress: abiEncodedSourceLinkPool, + RemotePoolAddresses: [][]byte{abiEncodedSourceLinkPool}, RemoteTokenAddress: abiEncodedSourceLinkTokenAddr, - Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, @@ -958,11 +964,11 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh require.NoError(t, err) _, err = destWrappedPool.ApplyChainUpdates( destUser, + []uint64{}, []lock_release_token_pool.TokenPoolChainUpdate{{ RemoteChainSelector: SourceChainSelector, - RemotePoolAddress: abiEncodedSourceWrappedPool, + RemotePoolAddresses: [][]byte{abiEncodedSourceWrappedPool}, RemoteTokenAddress: abiEncodedSourceWrappedTokenAddr, - Allowed: true, OutboundRateLimiterConfig: lock_release_token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: HundredLink, diff --git a/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go b/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go index 080e9b82e3..c9fbc9950d 100644 --- a/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go +++ b/core/services/ocr2/plugins/liquiditymanager/internal/integration_test.go @@ -657,7 +657,7 @@ func deployContracts( // deploy lock/release pool targeting the weth9 contract lockReleasePoolAddress, _, _, err := lock_release_token_pool.DeployLockReleaseTokenPool( - owner, backend, wethAddress, []common.Address{}, armProxyAddress, true, routerAddress) + owner, backend, wethAddress, 18, []common.Address{}, armProxyAddress, true, routerAddress) require.NoError(t, err, "failed to deploy LockReleaseTokenPool contract") backend.Commit() lockReleasePool, err := lock_release_token_pool.NewLockReleaseTokenPool(lockReleasePoolAddress, backend) diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index 579d16da4f..979b9a8bdd 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -505,6 +505,7 @@ func (e *CCIPContractsDeployer) DeployLockReleaseTokenPoolContract(tokenAddr str auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), token, + testhelpers.TokenDecimals, []common.Address{}, rmnProxy, true, diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 83fe12a60a..9b339560d6 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -478,14 +478,14 @@ func (w TokenPoolWrapper) IsSupportedChain(opts *bind.CallOpts, remoteChainSelec func (w TokenPoolWrapper) ApplyChainUpdates(opts *bind.TransactOpts, update []token_pool.TokenPoolChainUpdate) (*types.Transaction, error) { if w.Latest != nil && w.Latest.PoolInterface != nil { - return w.Latest.PoolInterface.ApplyChainUpdates(opts, update) + return w.Latest.PoolInterface.ApplyChainUpdates(opts, []uint64{}, update) } if w.V1_4_0 != nil && w.V1_4_0.PoolInterface != nil { V1_4_0Updates := make([]token_pool_1_4_0.TokenPoolChainUpdate, len(update)) for i, u := range update { V1_4_0Updates[i] = token_pool_1_4_0.TokenPoolChainUpdate{ RemoteChainSelector: u.RemoteChainSelector, - Allowed: u.Allowed, + Allowed: true, InboundRateLimiterConfig: token_pool_1_4_0.RateLimiterConfig{ IsEnabled: u.InboundRateLimiterConfig.IsEnabled, Capacity: u.InboundRateLimiterConfig.Capacity, @@ -828,9 +828,8 @@ func (pool *TokenPool) SetRemoteChainOnPool(remoteChainSelector uint64, remotePo selectorsToUpdate = append(selectorsToUpdate, token_pool.TokenPoolChainUpdate{ RemoteChainSelector: remoteChainSelector, - RemotePoolAddress: encodedPoolAddress, + RemotePoolAddresses: [][]byte{encodedPoolAddress}, RemoteTokenAddress: encodedTokenAddress, - Allowed: true, InboundRateLimiterConfig: token_pool.RateLimiterConfig{ IsEnabled: true, Capacity: new(big.Int).Mul(big.NewInt(1e18), big.NewInt(1e9)),