From ef923c333aecfd1548e115193f6b11702c931b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Evaldas=20Lato=C5=A1kinas?= <34982762+elatoskinas@users.noreply.github.com> Date: Fri, 19 Jul 2024 15:29:22 +0200 Subject: [PATCH] Family-agnostic ramps - refactor fee and family-specific logic to PriceRegistry (#1181) ## Motivation Lifts out family-specific fee & validation logic to the PriceRegistry - isolating fees calculations to the PriceRegistry state. The refactor converts the OnRamp to be fully dest-chain family agnostic - future additions of chain families would typically require only changing the PriceRegistry. ## Solution * Move the `DestChainConfig` to the PriceRegistry, and completely remove dest chain configs from the OnRamp. Since most of the dynamic config is specific to fee & chain logic (with the exception of `maxDataBytes` / `maxNumberOfTokens`), it is optimal to store the configs in a single contract * Moves all fee token configs to the PriceRegistry * Removes duplicate `_validateMessage`. Since the Router always calls `getFee` before `forwardFromRouter` - we can do the validations early in `getFee` * `PriceRegistry.getValidatedFee` - performs the previous `getFee` logic * `PriceRegistry.getValidatedRampMessageParams` - performs the chain-specific logic of `forwardFromRouter` - validating pool return data, computing message fees and determining out-of-order exec ![alt-chain-family-handling-design-Page-2 drawio (1)](https://github.com/user-attachments/assets/79603dde-6531-4d17-bf8b-ae80eaf0dbfc) ### Contract Sizes | Contract | Prev Size (kB) | Prev Margin (kB) | New Size (kB) | New Margin (kB) | |---------------------------------|------------------------------|---------------------------|---------------------------|---------------------------| | EVM2EVMMultiOnRamp | 22.6 | 1.976 | 9.944 | 14.632 | | PriceRegistry | 7.46 | 17.116 | 18.439 | 6.137 | | **Total** | 30.06 | | 28.383 | | ### Gas costs (e2e) | Function | Prev min-max | Prev avg | New min-max | New avg | |--------------|--------------|---------------|----------------|---------| | getFee (MultiOnRamp) | 0 - 47 501 | 20 357 | 0 - 38 863 | 16 655 | ccipSend (Router) | 287 347 - 375 060 | 341 643 | 279 728 - 367 441 | 334 024 --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Co-authored-by: Makram --- contracts/gas-snapshots/ccip.gas-snapshot | 695 +++---- .../scripts/native_solc_compile_all_ccip | 2 +- contracts/src/v0.8/ccip/PriceRegistry.sol | 605 +++++- .../v0.8/ccip/interfaces/IPriceRegistry.sol | 35 + .../v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol | 731 +------ contracts/src/v0.8/ccip/test/BaseTest.t.sol | 2 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 2 - .../MultiOnRampTokenPoolReentrancy.t.sol | 118 ++ .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 2 +- .../test/helpers/EVM2EVMMultiOnRampHelper.sol | 54 +- .../ccip/test/helpers/PriceRegistryHelper.sol | 72 + .../src/v0.8/ccip/test/mocks/MockRouter.sol | 2 +- .../ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol | 1586 +-------------- .../test/onRamp/EVM2EVMMultiOnRampSetup.t.sol | 233 +-- .../ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol | 3 - .../test/priceRegistry/PriceRegistry.t.sol | 1778 ++++++++++++++++- .../evm_2_evm_multi_onramp.go | 1165 ++--------- .../price_registry/price_registry.go | 1205 ++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 4 +- .../ccip/mocks/price_registry_interface.go | 716 ++++++- .../configs/evm/chain_writer.go | 2 +- .../configs/evm/contract_reader.go | 53 +- .../plugins/ccip_integration_tests/helpers.go | 79 +- .../ccip_integration_tests/ocr3_node_test.go | 12 +- .../ccip-tests/contracts/contract_deployer.go | 9 +- .../ccip-tests/contracts/contract_models.go | 2 +- 26 files changed, 5173 insertions(+), 3994 deletions(-) create mode 100644 contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol create mode 100644 contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 7d78550762..5fc99a9a40 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -8,11 +8,11 @@ ARMProxyTest:test_ARMIsCursed_Success() (gas: 49740) AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 26920) AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19691) AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 40911) -AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15353) +AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15368) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19623) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21208) -AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16403) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19696) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21281) +AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16418) AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13047) AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18989) @@ -34,7 +34,7 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28675) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243552) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24260) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2131102) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2131281) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9495) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70755) CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363647) @@ -95,16 +95,16 @@ CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28670) CommitStore_report:test_InvalidInterval_Revert() (gas: 28610) CommitStore_report:test_InvalidRootRevert() (gas: 27843) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 55405) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 61201) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 55403) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53253) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59049) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53251) CommitStore_report:test_Paused_Revert() (gas: 21259) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 86394) +CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84242) CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56313) CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63969) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119274) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119420) CommitStore_report:test_Unhealthy_Revert() (gas: 44751) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 102837) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100758) CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27626) CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11325) CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143718) @@ -120,82 +120,82 @@ CommitStore_verify:test_Paused_Revert() (gas: 18496) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) DefensiveExampleTest:test_Recovery() (gas: 424253) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1102697) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38172) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108340) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116808) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460512) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95536) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12460) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90379) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105577) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15716) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13054) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 298567) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 239905) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 158866) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189306) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1103438) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38157) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108343) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116811) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460560) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95542) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12463) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90385) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105586) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15719) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13057) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 298564) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 239899) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 158863) +EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189303) EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 147582) EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 521508) -EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10456) -EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 15659) -EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67189) -EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59695) -EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58775) -EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6394845) -EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 5978075) -EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 108372) -EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 118374) -EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 108415) -EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353706) -EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 161272) -EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136244) -EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136825) -EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59043) -EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227655) -EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 119676) -EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77602) -EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 209115) -EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6389234) -EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47782) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5981117) -EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 157317) -EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103806) +EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10459) +EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 15662) +EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67195) +EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59698) +EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58778) +EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6394741) +EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 5977968) +EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106229) +EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116228) +EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106272) +EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351414) +EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159132) +EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136253) +EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136831) +EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59046) +EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227807) +EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117527) +EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77605) +EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 207057) +EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6389130) +EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47785) +EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5981174) +EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 157326) +EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103815) EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101686) -EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 159823) -EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101576) -EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101643) -EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17277) -EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1559403) -EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 342891) -EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 260175) -EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6445196) -EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6028145) -EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 27678) -EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 165178) -EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149134) -EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6807271) -EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17151) +EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 159832) +EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101585) +EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101652) +EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17280) +EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1559406) +EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 342924) +EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 260178) +EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6445247) +EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6028193) +EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 27681) +EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 165181) +EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149137) +EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6807322) +EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17154) EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18413) EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249368) EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20672) EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 201673) EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48860) EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48381) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 232765) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 89359) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 278143) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 93582) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 232798) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 89392) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 278146) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 93615) EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35083) -EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23910) +EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23907) EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 451358) -EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54472) +EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54475) EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35917) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154363) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154369) EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35317) -EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 181347) +EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 181353) EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 190627) -EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48050) +EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48053) EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 443030) EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251770) EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 173962) @@ -205,7 +205,7 @@ EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 391710) EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65899) EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80955) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 535423) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 535429) EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 480345) EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35763) EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 520344) @@ -213,161 +213,106 @@ EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 517712) EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 487848) EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 127921) EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 157144) -EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3650714) -EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118188) -EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87407) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75594) +EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3655340) +EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118224) +EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87461) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75600) EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26461) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 163081) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 207379) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26001) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152861) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26004) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152867) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 507480) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2307922) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2307925) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 209633) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 210210) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 668610) EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 299477) EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 160598) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24128) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 59102) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 40402) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 76127) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178948) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 278810) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11376) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215388) -EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14371) -EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11895) -EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 14051) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55768) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33778) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 237989) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246652) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 299484) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24131) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 59105) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 40405) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 76130) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178951) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 278805) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215406) +EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14374) +EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11898) +EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 14054) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55771) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33781) +EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 238004) +EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246667) +EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 299499) EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 280579) -EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176586) -EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178657) -EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141518) -EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51505) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16764) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 33948) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16639) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16689) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput() (gas: 12380) -EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 174823) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11427) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 53981) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44763) -EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12280) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86785) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17084) -EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12268) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkChainSelectorEqZero_Revert() (gas: 143079) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigLinkTokenEqAddressZero_Revert() (gas: 138694) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 140980) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 146001) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 141047) -EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 5339882) -EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsDefault_Success() (gas: 18235) -EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 22580) -EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 19677) -EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 19202) -EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsV1_Success() (gas: 19292) -EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EVMExtraArgsV2_Success() (gas: 19431) -EVM2EVMMultiOnRamp_convertParsedExtraArgs:test_EmptyExtraArgs_Success() (gas: 19657) -EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 105045) -EVM2EVMMultiOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 109171) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 138298) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 169110) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 168533) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 167939) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 168807) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 168168) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 31992) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 27934) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidEVMAddressDestToken_Revert() (gas: 3524761) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidEVMAddress_Revert() (gas: 32153) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 37364) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 38327) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107541) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 152050) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 33654) -EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 23015) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 41465) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25860) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 242454) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 268460) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 152623) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 179557) -EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3819345) -EVM2EVMMultiOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 29961) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 44169) -EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 144078) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 249852) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 107139) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 283768) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 125164) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 12013) -EVM2EVMMultiOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 24707) -EVM2EVMMultiOnRamp_getFee:test_DestinationChainNotEnabled_Revert() (gas: 15422) -EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 101701) -EVM2EVMMultiOnRamp_getFee:test_HighGasMessage_Success() (gas: 258295) -EVM2EVMMultiOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 42444) -EVM2EVMMultiOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95014) -EVM2EVMMultiOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 182823) -EVM2EVMMultiOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 21839) -EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 141232) -EVM2EVMMultiOnRamp_getFee:test_TooManyTokens_Revert() (gas: 17439) -EVM2EVMMultiOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 83447) -EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) -EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 47313) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 35291) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28365) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130125) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15233) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28173) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21243) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 41226) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28196) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40557) -EVM2EVMMultiOnRamp_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 31676) +EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176604) +EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178672) +EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141533) +EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51508) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94528) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92480) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97483) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92538) +EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 2260144) +EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 90987) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 130983) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 161753) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 161306) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 159506) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 161536) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 160928) +EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 26206) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 134082) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 24272) +EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12819) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 30695) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 15675) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 198276) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 224545) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 140840) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 162262) +EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3803257) +EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 127615) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 93044) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 282576) +EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 104423) +EVM2EVMMultiOnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 74041) +EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119755) +EVM2EVMMultiOnRamp_getFee:test_Unhealthy_Revert() (gas: 43657) +EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) +EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11356) EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12956) EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11313) EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16287) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 60060) -EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10816) -EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6731) -EVM2EVMMultiOnRamp_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6461) -EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97131) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 58439) +EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97185) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38028) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 108191) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_revert_Revert() (gas: 116732) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 391521) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 145166) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 787635) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 176135) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 391880) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 145379) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 788000) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 176208) EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29700) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 63325) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 44501) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 214005) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 306795) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 127492) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 254959) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 263550) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 335546) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 314297) -EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17096) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 214151) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 306912) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 127459) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 255047) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 263638) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 335707) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 314443) +EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17009) EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153427) EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5464875) EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144183) EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21345) EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36442) EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51701) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473429) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473575) EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 46423) EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152453) EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 101458) @@ -379,25 +324,25 @@ EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 15938 EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 174622) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 248634) EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115017) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409192) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409338) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54173) EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132056) EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52200) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 559886) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 499132) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 560178) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 499424) EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35442) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546695) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546987) EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64045) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 123223) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 143388) -EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20615) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 281758) -EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20264) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 219168) -EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48665) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48153) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 316367) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 72555) +EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20582) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 281891) +EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20231) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 219228) +EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48632) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48120) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 316477) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 72423) EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 231326) EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 279867) EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 261109) @@ -406,15 +351,15 @@ EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 131682) EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38408) EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3213556) EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83091) -EVM2EVMOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 483468) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 186553) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 25894) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 43519) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 25997) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 188658) -EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 188105) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2027493) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143943) +EVM2EVMOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 483328) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 186413) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 25824) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 43449) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 25927) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 188518) +EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187965) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2027441) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143803) EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8871) EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40429) EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38804) @@ -423,57 +368,57 @@ EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_S EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16667) EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197660) EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5619710) -EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35784) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99476) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114216) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114258) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130130) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138656) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129810) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38260) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38376) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25517) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25303) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 85974) -EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36463) -EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29049) -EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107532) -EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22641) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 223458) -EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53941) -EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25487) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59096) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179147) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177361) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137118) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3731773) -EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30193) -EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43306) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109124) -EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312357) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112325) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72187) +EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35778) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99470) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114210) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114252) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130118) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138650) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129804) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38254) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38370) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25511) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25297) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86041) +EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36457) +EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29037) +EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107526) +EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22635) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 223665) +EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53935) +EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25481) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59303) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179141) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177355) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137297) +EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3731767) +EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30187) +EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43300) +EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109258) +EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312351) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112319) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72181) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147614) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190454) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121245) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95324) EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20760) EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 21128) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78186) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234034) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78242) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234090) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 158990) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159220) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24089) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117756) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117858) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19902) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 65635) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 65663) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45008) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45037) EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33041) EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28296) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130015) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130189) EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15260) EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28104) EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21248) @@ -591,28 +536,28 @@ MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Succes MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2085252) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30248) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47358) -MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15806) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19595) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21180) +MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15821) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14527) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189231) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 59854) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189450) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 59927) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17593) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 44895) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50452) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78488) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263218) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54638) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50598) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78780) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263510) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54784) MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 9223372036854754743) MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19104) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15778) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189219) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 61589) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189438) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 61662) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46683) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52225) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79553) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263432) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56395) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52371) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79845) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263724) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56541) MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwner_Revert() (gas: 11336) MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19124) MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10608) @@ -653,22 +598,23 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1455762) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 412349) +MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1426976) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 252566) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 254872) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 254866) NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 307885) NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 290962) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 247990) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236024) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 144774) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 185418) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 241823) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 124909) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 133171) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 186669) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 237737) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 124995) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 125923) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122899) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) @@ -700,47 +646,112 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51686) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 380130) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 148352) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 380360) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 148380) PingPong_plumbing:test_Pausing_Success() (gas: 17803) -PingPong_startPingPong:test_StartPingPong_Success() (gas: 178284) -PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79823) -PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12580) -PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 67418) -PriceRegistry_constructor:test_Setup_Success() (gas: 1870666) -PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72712) -PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30917) -PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70421) -PriceRegistry_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16816) -PriceRegistry_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16118) -PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45566) -PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62166) -PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84739) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094281) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094239) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074358) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094013) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094217) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094029) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 61896) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61776) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 60969) -PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093741) -PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61496) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109012) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13790) -PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092419) -PriceRegistry_updatePrices:test_OnlyCallableByUpdaterOrOwner_Revert() (gas: 14240) -PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23436) -PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30424) -PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 89738) -PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151078) -PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50483) -PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63448) -PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19932) -PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88796) -PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50733) -PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) +PingPong_startPingPong:test_StartPingPong_Success() (gas: 178340) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16719) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 16784) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16611) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16675) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 40953) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12341) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 139564) +PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80002) +PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11465) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54149) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44835) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12301) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86826) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17045) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) +PriceRegistry_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 105966) +PriceRegistry_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110316) +PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110369) +PriceRegistry_constructor:test_Setup_Success() (gas: 4650895) +PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) +PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) +PriceRegistry_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 95575) +PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14636) +PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20614) +PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70449) +PriceRegistry_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) +PriceRegistry_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) +PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45734) +PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62311) +PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84774) +PriceRegistry_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41283) +PriceRegistry_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34733) +PriceRegistry_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27807) +PriceRegistry_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 108018) +PriceRegistry_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20359) +PriceRegistry_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27615) +PriceRegistry_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 40668) +PriceRegistry_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27638) +PriceRegistry_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40015) +PriceRegistry_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29343) +PriceRegistry_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18203) +PriceRegistry_getValidatedFee:test_EmptyMessage_Success() (gas: 81464) +PriceRegistry_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 55184) +PriceRegistry_getValidatedFee:test_HighGasMessage_Success() (gas: 237926) +PriceRegistry_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19971) +PriceRegistry_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31775) +PriceRegistry_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97714) +PriceRegistry_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143193) +PriceRegistry_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29435) +PriceRegistry_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112283) +PriceRegistry_getValidatedFee:test_TooManyTokens_Revert() (gas: 20107) +PriceRegistry_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62956) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094532) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094490) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074609) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094264) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094468) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094280) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 61997) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61877) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 60998) +PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093992) +PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61525) +PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109113) +PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13819) +PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092670) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17360) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21454) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18551) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18075) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18452) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18569) +PriceRegistry_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18306) +PriceRegistry_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18852) +PriceRegistry_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16360) +PriceRegistry_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26236) +PriceRegistry_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32410) +PriceRegistry_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25848) +PriceRegistry_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23663) +PriceRegistry_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17320) +PriceRegistry_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12080) +PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) +PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30637) +PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76043) +PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151521) +PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50699) +PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63882) +PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19998) +PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89162) +PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50949) +PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12362) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10572) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3916546) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10756) +PriceRegistry_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6660) +PriceRegistry_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6440) +PriceRegistry_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 35457) +PriceRegistry_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 90631) +PriceRegistry_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 32749) +PriceRegistry_validatePoolReturnData:test_WithSingleToken_Success() (gas: 31293) RMN_constructor:test_Constructor_Success() (gas: 48838) RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19666) RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152152) @@ -820,24 +831,24 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89288) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10642128) Router_applyRampUpdates:test_OnRampDisable() (gas: 55913) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12311) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113833) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 200606) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128441) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215216) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66247) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113861) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 200634) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128508) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215283) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66275) Router_ccipSend:test_InvalidMsgValue() (gas: 31963) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68683) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173510) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56009) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 172104) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242617) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68711) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173605) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56037) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 172199) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242707) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24749) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44724) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174320) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 242860) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174415) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 245121) Router_constructor:test_Constructor_Success() (gas: 13074) Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46436) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46464) Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17138) Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) @@ -852,7 +863,7 @@ Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25116) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44724) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10985) SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 53540) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 416762) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 416930) SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20157) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51085) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43947) @@ -878,8 +889,8 @@ TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Re TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49390) TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6036775) TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6282531) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6883313) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7067428) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6883397) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7067512) TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2169749) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12089) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23280) @@ -908,16 +919,16 @@ TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 1559 TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13173) TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281890) TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17109) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136323) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136351) TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15919) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 244416) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 244483) TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16303) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261055) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261100) TokenProxy_constructor:test_Constructor() (gas: 13812) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16827) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12658) TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15849) -TokenProxy_getFee:test_GetFee_Success() (gas: 86892) +TokenProxy_getFee:test_GetFee_Success() (gas: 86948) USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 24960) USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35312) USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30063) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 6228655d87..1dbb70502d 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -36,7 +36,7 @@ compileContract () { echo "MultiOffRamp uses $OPTIMIZE_RUNS_MULTI_OFFRAMP optimizer runs." optimize_runs=$OPTIMIZE_RUNS_MULTI_OFFRAMP ;; - "ccip/onRamp/EVM2EVMMultiOnRamp.sol" | "ccip/onRamp/EVM2EVMOnRamp.sol") + "ccip/onRamp/EVM2EVMOnRamp.sol") echo "OnRamp uses $OPTIMIZE_RUNS_ONRAMP optimizer runs." optimize_runs=$OPTIMIZE_RUNS_ONRAMP ;; diff --git a/contracts/src/v0.8/ccip/PriceRegistry.sol b/contracts/src/v0.8/ccip/PriceRegistry.sol index e1baf1a345..f15232271e 100644 --- a/contracts/src/v0.8/ccip/PriceRegistry.sol +++ b/contracts/src/v0.8/ccip/PriceRegistry.sol @@ -6,7 +6,9 @@ import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; import {AggregatorV3Interface} from "./../shared/interfaces/AggregatorV3Interface.sol"; +import {Client} from "./libraries/Client.sol"; import {Internal} from "./libraries/Internal.sol"; +import {Pool} from "./libraries/Pool.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; import {EnumerableSet} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; @@ -24,11 +26,30 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { IPriceRegistry.TokenPriceFeedConfig feedConfig; // Feed config update data } + /// @dev Struct that contains the static configuration + /// RMN depends on this struct, if changing, please notify the RMN maintainers. + // solhint-disable-next-line gas-struct-packing + struct StaticConfig { + uint96 maxFeeJuelsPerMsg; // ─╮ Maximum fee that can be charged for a message + address linkToken; // ────────╯ LINK token address + uint32 stalenessThreshold; // The amount of time a gas price can be stale before it is considered invalid. + } + error TokenNotSupported(address token); error ChainNotSupported(uint64 chain); error StaleGasPrice(uint64 destChainSelector, uint256 threshold, uint256 timePassed); - error InvalidStalenessThreshold(); error DataFeedValueOutOfUint224Range(); + error InvalidDestBytesOverhead(address token, uint32 destBytesOverhead); + error MessageGasLimitTooHigh(); + error DestinationChainNotEnabled(uint64 destChainSelector); + error ExtraArgOutOfOrderExecutionMustBeTrue(); + error InvalidExtraArgsTag(); + error SourceTokenDataTooLarge(address token); + error InvalidDestChainConfig(uint64 destChainSelector); + error MessageFeeTooHigh(uint256 msgFeeJuels, uint256 maxFeeJuelsPerMsg); + error InvalidStaticConfig(); + error MessageTooLarge(uint256 maxSize, uint256 actualSize); + error UnsupportedNumberOfTokens(); event PriceUpdaterSet(address indexed priceUpdater); event PriceUpdaterRemoved(address indexed priceUpdater); @@ -38,6 +59,86 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp); event PriceFeedPerTokenUpdated(address indexed token, IPriceRegistry.TokenPriceFeedConfig priceFeedConfig); + event TokenTransferFeeConfigUpdated( + uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig + ); + event TokenTransferFeeConfigDeleted(uint64 indexed destChainSelector, address indexed token); + event PremiumMultiplierWeiPerEthUpdated(address indexed token, uint64 premiumMultiplierWeiPerEth); + event DestChainConfigUpdated(uint64 indexed destChainSelector, DestChainConfig destChainConfig); + event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); + + /// @dev Struct to hold the fee & validation configs for a destination chain + struct DestChainConfig { + bool isEnabled; // ──────────────────────────╮ Whether this destination chain is enabled + uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message + uint32 maxDataBytes; // │ Maximum payload data size in bytes + uint32 maxPerMsgGasLimit; // │ Maximum gas limit for messages targeting EVMs + uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs + uint16 destGasPerPayloadByte; // │ Destination chain gas charged for passing each byte of `data` payload to receiver + uint32 destDataAvailabilityOverheadGas; // | Extra data availability gas charged on top of the message, e.g. for OCR + uint16 destGasPerDataAvailabilityByte; // | Amount of gas to charge per byte of message data that needs availability + uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001 + // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token + uint16 defaultTokenFeeUSDCents; // │ Default token fee charged per token transfer + uint32 defaultTokenDestGasOverhead; // ──────╯ Default gas charged to execute the token transfer on the destination chain + uint32 defaultTokenDestBytesOverhead; // ────╮ Default extra data availability bytes charged per token transfer + uint32 defaultTxGasLimit; // │ Default gas limit for a tx + uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. + uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD + bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. + bytes4 chainFamilySelector; // ──────────────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. + } + + /// @dev Struct to hold the configs and its destination chain selector + /// Same as DestChainConfig but with the destChainSelector so that an array of these + /// can be passed in the constructor and the applyDestChainConfigUpdates function + //solhint-disable gas-struct-packing + struct DestChainConfigArgs { + uint64 destChainSelector; // Destination chain selector + DestChainConfig destChainConfig; // Config to update for the chain selector + } + + /// @dev Struct to hold the transfer fee configuration for token transfers + struct TokenTransferFeeConfig { + uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD + uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD + uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 + uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain + // │ Extra data availability bytes that are returned from the source pool and sent + uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees + } + + /// @dev Struct to hold the token transfer fee configurations for a token, same as TokenTransferFeeConfig but with the token address included so + /// that an array of these can be passed in the TokenTransferFeeConfigArgs struct to set the mapping + struct TokenTransferFeeConfigSingleTokenArgs { + address token; // Token address + TokenTransferFeeConfig tokenTransferFeeConfig; // struct to hold the transfer fee configuration for token transfers + } + + /// @dev Struct to hold the token transfer fee configurations for a destination chain and a set of tokens. Same as TokenTransferFeeConfigSingleTokenArgs + /// but with the destChainSelector and an array of TokenTransferFeeConfigSingleTokenArgs included so that an array of these can be passed in the constructor + /// and the applyTokenTransferFeeConfigUpdates function + struct TokenTransferFeeConfigArgs { + uint64 destChainSelector; // Destination chain selector + TokenTransferFeeConfigSingleTokenArgs[] tokenTransferFeeConfigs; // Array of token transfer fee configurations + } + + /// @dev Struct to hold a pair of destination chain selector and token address so that an array of these can be passed in the + /// applyTokenTransferFeeConfigUpdates function to remove the token transfer fee configuration for a token + struct TokenTransferFeeConfigRemoveArgs { + uint64 destChainSelector; // ─╮ Destination chain selector + address token; // ────────────╯ Token address + } + + /// @dev Struct to hold the fee token configuration for a token, same as the s_premiumMultiplierWeiPerEth but with + /// the token address included so that an array of these can be passed in the constructor and + /// applyPremiumMultiplierWeiPerEthUpdates to set the mapping + struct PremiumMultiplierWeiPerEthArgs { + address token; // // ───────────────────╮ Token address + uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. Should never be 0 so can be used as an isEnabled flag + } + string public constant override typeAndVersion = "PriceRegistry 1.6.0-dev"; /// @dev The gas price per unit of gas for a given destination chain, in USD with 18 decimals. @@ -61,6 +162,22 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { /// @dev Stores the price data feed configurations per token. mapping(address token => IPriceRegistry.TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; + /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin + /// This should never be 0 once set, so it can be used as an isEnabled flag + mapping(address token => uint64 premiumMultiplierWeiPerEth) internal s_premiumMultiplierWeiPerEth; + + /// @dev The destination chain specific fee configs + mapping(uint64 destChainSelector => DestChainConfig destChainConfig) internal s_destChainConfigs; + + /// @dev The token transfer fee config that can be set by the owner or fee admin + mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) internal + s_tokenTransferFeeConfig; + + /// @dev Maximum fee that can be charged for a message. This is a guard to prevent massively overcharging due to misconfiguation. + uint96 internal immutable i_maxFeeJuelsPerMsg; + /// @dev The link token address + address internal immutable i_linkToken; + // Price updaters are allowed to update the prices. EnumerableSet.AddressSet private s_priceUpdaters; // Subset of tokens which prices tracked by this registry which are fee tokens. @@ -69,15 +186,30 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { uint32 private immutable i_stalenessThreshold; constructor( + StaticConfig memory staticConfig, address[] memory priceUpdaters, address[] memory feeTokens, - uint32 stalenessThreshold, - TokenPriceFeedUpdate[] memory tokenPriceFeeds + TokenPriceFeedUpdate[] memory tokenPriceFeeds, + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, + DestChainConfigArgs[] memory destChainConfigArgs ) AuthorizedCallers(priceUpdaters) { + if ( + staticConfig.linkToken == address(0) || staticConfig.maxFeeJuelsPerMsg == 0 + || staticConfig.stalenessThreshold == 0 + ) { + revert InvalidStaticConfig(); + } + + i_linkToken = staticConfig.linkToken; + i_maxFeeJuelsPerMsg = staticConfig.maxFeeJuelsPerMsg; + i_stalenessThreshold = staticConfig.stalenessThreshold; + _applyFeeTokensUpdates(feeTokens, new address[](0)); _updateTokenPriceFeeds(tokenPriceFeeds); - if (stalenessThreshold == 0) revert InvalidStalenessThreshold(); - i_stalenessThreshold = stalenessThreshold; + _applyDestChainConfigUpdates(destChainConfigArgs); + _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, new TokenTransferFeeConfigRemoveArgs[](0)); } // ================================================================ @@ -124,12 +256,6 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { return s_usdPriceFeedsPerToken[token]; } - /// @notice Get the staleness threshold. - /// @return stalenessThreshold The staleness threshold. - function getStalenessThreshold() external view returns (uint128) { - return i_stalenessThreshold; - } - /// @inheritdoc IPriceRegistry function getDestinationChainGasPrice(uint64 destChainSelector) external @@ -144,7 +270,7 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { function getTokenAndGasPrices( address token, uint64 destChainSelector - ) external view override returns (uint224 tokenPrice, uint224 gasPriceValue) { + ) public view override returns (uint224 tokenPrice, uint224 gasPriceValue) { Internal.TimestampedPackedUint224 memory gasPrice = s_usdPerUnitGasByDestChainSelector[destChainSelector]; // We do allow a gas price of 0, but no stale or unset gas prices if (gasPrice.timestamp == 0) revert ChainNotSupported(destChainSelector); @@ -162,7 +288,7 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { address fromToken, uint256 fromTokenAmount, address toToken - ) external view override returns (uint256) { + ) public view override returns (uint256) { /// Example: /// fromTokenAmount: 1e18 // 1 ETH /// ETH: 2_000e18 @@ -272,7 +398,10 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { // ================================================================ /// @inheritdoc IPriceRegistry - function updatePrices(Internal.PriceUpdates calldata priceUpdates) external override requireUpdaterOrOwner { + function updatePrices(Internal.PriceUpdates calldata priceUpdates) external override { + // The caller must be the fee updater + _validateCaller(); + uint256 tokenUpdatesLength = priceUpdates.tokenPriceUpdates.length; for (uint256 i = 0; i < tokenUpdatesLength; ++i) { @@ -312,14 +441,448 @@ contract PriceRegistry is AuthorizedCallers, IPriceRegistry, ITypeAndVersion { } // ================================================================ - // │ Access │ + // │ Fee quoting │ // ================================================================ - /// @notice Require that the caller is the owner or a fee updater. - modifier requireUpdaterOrOwner() { - if (msg.sender != owner()) { - // if not owner - check if the caller is a fee updater - _validateCaller(); + + /// @inheritdoc IPriceRegistry + /// @dev The function should always validate message.extraArgs, message.receiver and family-specific configs + function getValidatedFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount) { + DestChainConfig memory destChainConfig = s_destChainConfigs[destChainSelector]; + if (!destChainConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); + + uint256 numberOfTokens = message.tokenAmounts.length; + _validateMessage(destChainConfig, message.data.length, numberOfTokens, message.receiver); + + uint64 premiumMultiplierWeiPerEth = s_premiumMultiplierWeiPerEth[message.feeToken]; + + // The below call asserts that feeToken is a supported token + (uint224 feeTokenPrice, uint224 packedGasPrice) = getTokenAndGasPrices(message.feeToken, destChainSelector); + + // Calculate premiumFee in USD with 18 decimals precision first. + // If message-only and no token transfers, a flat network fee is charged. + // If there are token transfers, premiumFee is calculated from token transfer fee. + // If there are both token transfers and message, premiumFee is only calculated from token transfer fee. + uint256 premiumFee = 0; + uint32 tokenTransferGas = 0; + uint32 tokenTransferBytesOverhead = 0; + if (numberOfTokens > 0) { + (premiumFee, tokenTransferGas, tokenTransferBytesOverhead) = + _getTokenTransferCost(destChainConfig, destChainSelector, message.feeToken, feeTokenPrice, message.tokenAmounts); + } else { + // Convert USD cents with 2 decimals to 18 decimals. + premiumFee = uint256(destChainConfig.networkFeeUSDCents) * 1e16; + } + + // Calculate data availability cost in USD with 36 decimals. Data availability cost exists on rollups that need to post + // transaction calldata onto another storage layer, e.g. Eth mainnet, incurring additional storage gas costs. + uint256 dataAvailabilityCost = 0; + + // Only calculate data availability cost if data availability multiplier is non-zero. + // The multiplier should be set to 0 if destination chain does not charge data availability cost. + if (destChainConfig.destDataAvailabilityMultiplierBps > 0) { + dataAvailabilityCost = _getDataAvailabilityCost( + destChainConfig, + // Parse the data availability gas price stored in the higher-order 112 bits of the encoded gas price. + uint112(packedGasPrice >> Internal.GAS_PRICE_BITS), + message.data.length, + numberOfTokens, + tokenTransferBytesOverhead + ); } - _; + + // Calculate execution gas fee on destination chain in USD with 36 decimals. + // We add the message gas limit, the overhead gas, the gas of passing message data to receiver, and token transfer gas together. + // We then multiply this gas total with the gas multiplier and gas price, converting it into USD with 36 decimals. + // uint112(packedGasPrice) = executionGasPrice + + // NOTE: when supporting non-EVM chains, revisit how generic this fee logic can be + // NOTE: revisit parsing non-EVM args + + uint256 executionCost = uint112(packedGasPrice) + * ( + destChainConfig.destGasOverhead + (message.data.length * destChainConfig.destGasPerPayloadByte) + tokenTransferGas + + _parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig).gasLimit + ) * destChainConfig.gasMultiplierWeiPerEth; + + // Calculate number of fee tokens to charge. + // Total USD fee is in 36 decimals, feeTokenPrice is in 18 decimals USD for 1e18 smallest token denominations. + // Result of the division is the number of smallest token denominations. + return ((premiumFee * premiumMultiplierWeiPerEth) + executionCost + dataAvailabilityCost) / feeTokenPrice; + } + + /// @notice Sets the fee configuration for a token + /// @param premiumMultiplierWeiPerEthArgs Array of PremiumMultiplierWeiPerEthArgs structs. + function applyPremiumMultiplierWeiPerEthUpdates( + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs + ) external onlyOwner { + _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + } + + /// @dev Set the fee config. + /// @param premiumMultiplierWeiPerEthArgs The multiplier for destination chain specific premiums. + function _applyPremiumMultiplierWeiPerEthUpdates( + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs + ) internal { + for (uint256 i = 0; i < premiumMultiplierWeiPerEthArgs.length; ++i) { + address token = premiumMultiplierWeiPerEthArgs[i].token; + uint64 premiumMultiplierWeiPerEth = premiumMultiplierWeiPerEthArgs[i].premiumMultiplierWeiPerEth; + s_premiumMultiplierWeiPerEth[token] = premiumMultiplierWeiPerEth; + + emit PremiumMultiplierWeiPerEthUpdated(token, premiumMultiplierWeiPerEth); + } + } + + /// @notice Gets the fee configuration for a token. + /// @param token The token to get the fee configuration for. + /// @return premiumMultiplierWeiPerEth The multiplier for destination chain specific premiums. + function getPremiumMultiplierWeiPerEth(address token) external view returns (uint64 premiumMultiplierWeiPerEth) { + return s_premiumMultiplierWeiPerEth[token]; + } + + /// @notice Returns the token transfer cost parameters. + /// A basis point fee is calculated from the USD value of each token transfer. + /// For each individual transfer, this fee is between [minFeeUSD, maxFeeUSD]. + /// Total transfer fee is the sum of each individual token transfer fee. + /// @dev Assumes that tokenAmounts are validated to be listed tokens elsewhere. + /// @dev Splitting one token transfer into multiple transfers is discouraged, + /// as it will result in a transferFee equal or greater than the same amount aggregated/de-duped. + /// @param destChainConfig the config configured for the destination chain selector. + /// @param destChainSelector the destination chain selector. + /// @param feeToken address of the feeToken. + /// @param feeTokenPrice price of feeToken in USD with 18 decimals. + /// @param tokenAmounts token transfers in the message. + /// @return tokenTransferFeeUSDWei total token transfer bps fee in USD with 18 decimals. + /// @return tokenTransferGas total execution gas of the token transfers. + /// @return tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. + function _getTokenTransferCost( + DestChainConfig memory destChainConfig, + uint64 destChainSelector, + address feeToken, + uint224 feeTokenPrice, + Client.EVMTokenAmount[] calldata tokenAmounts + ) internal view returns (uint256 tokenTransferFeeUSDWei, uint32 tokenTransferGas, uint32 tokenTransferBytesOverhead) { + uint256 numberOfTokens = tokenAmounts.length; + + for (uint256 i = 0; i < numberOfTokens; ++i) { + Client.EVMTokenAmount memory tokenAmount = tokenAmounts[i]; + TokenTransferFeeConfig memory transferFeeConfig = s_tokenTransferFeeConfig[destChainSelector][tokenAmount.token]; + + // If the token has no specific overrides configured, we use the global defaults. + if (!transferFeeConfig.isEnabled) { + tokenTransferFeeUSDWei += uint256(destChainConfig.defaultTokenFeeUSDCents) * 1e16; + tokenTransferGas += destChainConfig.defaultTokenDestGasOverhead; + tokenTransferBytesOverhead += destChainConfig.defaultTokenDestBytesOverhead; + continue; + } + + uint256 bpsFeeUSDWei = 0; + // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token. + // Useful for when the PriceRegistry cannot return a valid price for the token. + if (transferFeeConfig.deciBps > 0) { + uint224 tokenPrice = 0; + if (tokenAmount.token != feeToken) { + tokenPrice = _getValidatedTokenPrice(tokenAmount.token); + } else { + tokenPrice = feeTokenPrice; + } + + // Calculate token transfer value, then apply fee ratio + // ratio represents multiples of 0.1bps, or 1e-5 + bpsFeeUSDWei = (tokenPrice._calcUSDValueFromTokenAmount(tokenAmount.amount) * transferFeeConfig.deciBps) / 1e5; + } + + tokenTransferGas += transferFeeConfig.destGasOverhead; + tokenTransferBytesOverhead += transferFeeConfig.destBytesOverhead; + + // Bps fees should be kept within range of [minFeeUSD, maxFeeUSD]. + // Convert USD values with 2 decimals to 18 decimals. + uint256 minFeeUSDWei = uint256(transferFeeConfig.minFeeUSDCents) * 1e16; + if (bpsFeeUSDWei < minFeeUSDWei) { + tokenTransferFeeUSDWei += minFeeUSDWei; + continue; + } + + uint256 maxFeeUSDWei = uint256(transferFeeConfig.maxFeeUSDCents) * 1e16; + if (bpsFeeUSDWei > maxFeeUSDWei) { + tokenTransferFeeUSDWei += maxFeeUSDWei; + continue; + } + + tokenTransferFeeUSDWei += bpsFeeUSDWei; + } + + return (tokenTransferFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead); + } + + /// @notice Returns the estimated data availability cost of the message. + /// @dev To save on gas, we use a single destGasPerDataAvailabilityByte value for both zero and non-zero bytes. + /// @param destChainConfig the config configured for the destination chain selector. + /// @param dataAvailabilityGasPrice USD per data availability gas in 18 decimals. + /// @param messageDataLength length of the data field in the message. + /// @param numberOfTokens number of distinct token transfers in the message. + /// @param tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. + /// @return dataAvailabilityCostUSD36Decimal total data availability cost in USD with 36 decimals. + function _getDataAvailabilityCost( + DestChainConfig memory destChainConfig, + uint112 dataAvailabilityGasPrice, + uint256 messageDataLength, + uint256 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) internal pure returns (uint256 dataAvailabilityCostUSD36Decimal) { + // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields. + // Fixed message fields do account for the offset and length slot of the dynamic fields. + uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + + // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost. + // Its value is determined by CCIP lane implementation, e.g. the overhead data posted for OCR. + uint256 dataAvailabilityGas = (dataAvailabilityLengthBytes * destChainConfig.destGasPerDataAvailabilityByte) + + destChainConfig.destDataAvailabilityOverheadGas; + + // dataAvailabilityGasPrice is in 18 decimals, destDataAvailabilityMultiplierBps is in 4 decimals + // We pad 14 decimals to bring the result to 36 decimals, in line with token bps and execution fee. + return ((dataAvailabilityGas * dataAvailabilityGasPrice) * destChainConfig.destDataAvailabilityMultiplierBps) * 1e14; + } + + /// @notice Gets the transfer fee config for a given token. + /// @param destChainSelector The destination chain selector. + /// @param token The token address. + function getTokenTransferFeeConfig( + uint64 destChainSelector, + address token + ) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) { + return s_tokenTransferFeeConfig[destChainSelector][token]; + } + + /// @notice Sets the transfer fee config. + /// @dev only callable by the owner or admin. + function applyTokenTransferFeeConfigUpdates( + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs + ) external onlyOwner { + _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs); + } + + /// @notice internal helper to set the token transfer fee config. + function _applyTokenTransferFeeConfigUpdates( + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs + ) internal { + for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { + TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = tokenTransferFeeConfigArgs[i]; + uint64 destChainSelector = tokenTransferFeeConfigArg.destChainSelector; + + for (uint256 j = 0; j < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++j) { + TokenTransferFeeConfig memory tokenTransferFeeConfig = + tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].tokenTransferFeeConfig; + address token = tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].token; + + if (tokenTransferFeeConfig.destBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { + revert InvalidDestBytesOverhead(token, tokenTransferFeeConfig.destBytesOverhead); + } + + s_tokenTransferFeeConfig[destChainSelector][token] = tokenTransferFeeConfig; + + emit TokenTransferFeeConfigUpdated(destChainSelector, token, tokenTransferFeeConfig); + } + } + + // Remove the custom fee configs for the tokens that are in the tokensToUseDefaultFeeConfigs array + for (uint256 i = 0; i < tokensToUseDefaultFeeConfigs.length; ++i) { + uint64 destChainSelector = tokensToUseDefaultFeeConfigs[i].destChainSelector; + address token = tokensToUseDefaultFeeConfigs[i].token; + delete s_tokenTransferFeeConfig[destChainSelector][token]; + emit TokenTransferFeeConfigDeleted(destChainSelector, token); + } + } + + // ================================================================ + // │ Validations & message processing │ + // ================================================================ + + /// @notice Validates that the destAddress matches the expected format of the family. + /// @param chainFamilySelector Tag to identify the target family + /// @param destAddress Dest address to validate + /// @dev precondition - assumes the family tag is correct and validated + function _validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) internal pure { + if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { + Internal._validateEVMAddress(destAddress); + } + } + + /// @dev Convert the extra args bytes into a struct with validations against the dest chain config + /// @param extraArgs The extra args bytes + /// @param destChainConfig Dest chain config to validate against + /// @return EVMExtraArgs the extra args struct (latest version) + function _parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) internal pure returns (Client.EVMExtraArgsV2 memory) { + Client.EVMExtraArgsV2 memory evmExtraArgs = + _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, destChainConfig.defaultTxGasLimit); + + if (evmExtraArgs.gasLimit > uint256(destChainConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); + if (destChainConfig.enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { + revert ExtraArgOutOfOrderExecutionMustBeTrue(); + } + + return evmExtraArgs; + } + + /// @dev Convert the extra args bytes into a struct + /// @param extraArgs The extra args bytes + /// @param defaultTxGasLimit default tx gas limit to use in the absence of extra args + /// @return EVMExtraArgs the extra args struct (latest version) + function _parseUnvalidatedEVMExtraArgsFromBytes( + bytes calldata extraArgs, + uint64 defaultTxGasLimit + ) private pure returns (Client.EVMExtraArgsV2 memory) { + if (extraArgs.length == 0) { + // If extra args are empty, generate default values + return Client.EVMExtraArgsV2({gasLimit: defaultTxGasLimit, allowOutOfOrderExecution: false}); + } + + bytes4 extraArgsTag = bytes4(extraArgs); + bytes memory argsData = extraArgs[4:]; + + if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { + return abi.decode(argsData, (Client.EVMExtraArgsV2)); + } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { + // EVMExtraArgsV1 originally included a second boolean (strict) field which has been deprecated. + // Clients may still include it but it will be ignored. + return Client.EVMExtraArgsV2({gasLimit: abi.decode(argsData, (uint256)), allowOutOfOrderExecution: false}); + } + + revert InvalidExtraArgsTag(); + } + + /// @notice Validate the forwarded message to ensure it matches the configuration limits (message length, number of tokens) + /// and family-specific expectations (address format) + /// @param destChainConfig Dest chain config + /// @param dataLength The length of the data field of the message. + /// @param numberOfTokens The number of tokens to be sent. + /// @param receiver Message receiver on the dest chain + function _validateMessage( + DestChainConfig memory destChainConfig, + uint256 dataLength, + uint256 numberOfTokens, + bytes memory receiver + ) internal pure { + // Check that payload is formed correctly + if (dataLength > uint256(destChainConfig.maxDataBytes)) { + revert MessageTooLarge(uint256(destChainConfig.maxDataBytes), dataLength); + } + if (numberOfTokens > uint256(destChainConfig.maxNumberOfTokensPerMsg)) revert UnsupportedNumberOfTokens(); + _validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver); + } + + /// @inheritdoc IPriceRegistry + function processMessageArgs( + uint64 destChainSelector, + address feeToken, + uint256 feeTokenAmount, + bytes calldata extraArgs + ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) { + // Convert feeToken to link if not already in link + if (feeToken == i_linkToken) { + msgFeeJuels = feeTokenAmount; + } else { + msgFeeJuels = convertTokenAmount(feeToken, feeTokenAmount, i_linkToken); + } + + if (msgFeeJuels > i_maxFeeJuelsPerMsg) revert MessageFeeTooHigh(msgFeeJuels, i_maxFeeJuelsPerMsg); + + uint64 defaultTxGasLimit = s_destChainConfigs[destChainSelector].defaultTxGasLimit; + // NOTE: when supporting non-EVM chains, revisit this and parse non-EVM args. + // We can parse unvalidated args since this message is called after getFee (which will already validate the params) + Client.EVMExtraArgsV2 memory parsedExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); + isOutOfOrderExecution = parsedExtraArgs.allowOutOfOrderExecution; + + return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs)); + } + + /// @inheritdoc IPriceRegistry + /// @dev precondition - rampTokenAmounts and sourceTokenAmounts lengths must be equal + function validatePoolReturnData( + uint64 destChainSelector, + Internal.RampTokenAmount[] calldata rampTokenAmounts, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) external view { + bytes4 chainFamilySelector = s_destChainConfigs[destChainSelector].chainFamilySelector; + + for (uint256 i = 0; i < rampTokenAmounts.length; ++i) { + address sourceToken = sourceTokenAmounts[i].token; + + // Since the DON has to pay for the extraData to be included on the destination chain, we cap the length of the + // extraData. This prevents gas bomb attacks on the NOPs. As destBytesOverhead accounts for both + // extraData and offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData. + uint256 destPoolDataLength = rampTokenAmounts[i].extraData.length; + if (destPoolDataLength > Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { + if (destPoolDataLength > s_tokenTransferFeeConfig[destChainSelector][sourceToken].destBytesOverhead) { + revert SourceTokenDataTooLarge(sourceToken); + } + } + + _validateDestFamilyAddress(chainFamilySelector, rampTokenAmounts[i].destTokenAddress); + } + } + + // ================================================================ + // │ Configs │ + // ================================================================ + + /// @notice Returns the configured config for the dest chain selector + /// @param destChainSelector destination chain selector to fetch config for + /// @return destChainConfig config for the dest chain + function getDestChainConfig(uint64 destChainSelector) external view returns (DestChainConfig memory) { + return s_destChainConfigs[destChainSelector]; + } + + /// @notice Updates the destination chain specific config. + /// @param destChainConfigArgs Array of source chain specific configs. + function applyDestChainConfigUpdates(DestChainConfigArgs[] memory destChainConfigArgs) external onlyOwner { + _applyDestChainConfigUpdates(destChainConfigArgs); + } + + /// @notice Internal version of applyDestChainConfigUpdates. + function _applyDestChainConfigUpdates(DestChainConfigArgs[] memory destChainConfigArgs) internal { + for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { + DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; + uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; + DestChainConfig memory destChainConfig = destChainConfigArg.destChainConfig; + + // NOTE: when supporting non-EVM chains, update chainFamilySelector validations + if ( + destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0 + || destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM + || destChainConfig.defaultTokenDestBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + || destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit + ) { + revert InvalidDestChainConfig(destChainSelector); + } + + // The chain family selector cannot be zero - indicates that it is a new chain + if (s_destChainConfigs[destChainSelector].chainFamilySelector == 0) { + emit DestChainAdded(destChainSelector, destChainConfig); + } else { + emit DestChainConfigUpdated(destChainSelector, destChainConfig); + } + + s_destChainConfigs[destChainSelector] = destChainConfig; + } + } + + /// @notice Returns the static PriceRegistry config. + /// @dev RMN depends on this function, if changing, please notify the RMN maintainers. + /// @return the configuration. + function getStaticConfig() external view returns (StaticConfig memory) { + return StaticConfig({ + maxFeeJuelsPerMsg: i_maxFeeJuelsPerMsg, + linkToken: i_linkToken, + stalenessThreshold: i_stalenessThreshold + }); } } diff --git a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol index f3c9bb0115..8a20299371 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; +import {Client} from "../libraries/Client.sol"; import {Internal} from "../libraries/Internal.sol"; interface IPriceRegistry { @@ -71,4 +72,38 @@ interface IPriceRegistry { /// @notice Get the list of fee tokens. /// @return The tokens set as fee tokens. function getFeeTokens() external view returns (address[] memory); + + /// @notice Validates the ccip message & returns the fee + /// @param destChainSelector The destination chain selector. + /// @param message The message to get quote for. + /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. + function getValidatedFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount); + + /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels + /// @param destChainSelector destination chain selector to process + /// @param feeToken Fee token address used to pay for message fees + /// @param feeTokenAmount Fee token amount + /// @param extraArgs Message extra args that were passed in by the client + /// @return msgFeeJuels message fee in juels + /// @return isOutOfOrderExecution true if the message should be executed out of order + /// @return convertedExtraArgs extra args converted to the latest family-specific args version + function processMessageArgs( + uint64 destChainSelector, + address feeToken, + uint256 feeTokenAmount, + bytes memory extraArgs + ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs); + + /// @notice Validates pool return data + /// @param destChainSelector Destination chain selector to which the token amounts are sent to + /// @param rampTokenAmounts Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message + function validatePoolReturnData( + uint64 destChainSelector, + Internal.RampTokenAmount[] calldata rampTokenAmounts, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) external view; } diff --git a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol index c67afeb321..fc455cc869 100644 --- a/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol @@ -30,43 +30,26 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre error InvalidExtraArgsTag(); error ExtraArgOutOfOrderExecutionMustBeTrue(); error OnlyCallableByOwnerOrAdmin(); - error MessageTooLarge(uint256 maxSize, uint256 actualSize); error MessageGasLimitTooHigh(); - error MessageFeeTooHigh(uint256 msgFeeJuels, uint256 maxFeeJuelsPerMsg); - error UnsupportedNumberOfTokens(); error UnsupportedToken(address token); error MustBeCalledByRouter(); error RouterMustSetOriginalSender(); error InvalidConfig(); error CursedByRMN(uint64 sourceChainSelector); - error NotAFeeToken(address token); - error SourceTokenDataTooLarge(address token); error GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); - error InvalidDestChainConfig(uint64 destChainSelector); - error DestinationChainNotEnabled(uint64 destChainSelector); - error InvalidDestBytesOverhead(address token, uint32 destBytesOverhead); event AdminSet(address newAdmin); event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); event FeePaid(address indexed feeToken, uint256 feeValueJuels); event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); - event PremiumMultiplierWeiPerEthUpdated(address indexed token, uint64 premiumMultiplierWeiPerEth); - event TokenTransferFeeConfigUpdated( - uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig - ); - event TokenTransferFeeConfigDeleted(uint64 indexed destChainSelector, address indexed token); /// RMN depends on this event, if changing, please notify the RMN maintainers. event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); - event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); - event DestChainDynamicConfigUpdated(uint64 indexed destChainSelector, DestChainDynamicConfig dynamicConfig); /// @dev Struct that contains the static configuration /// RMN depends on this struct, if changing, please notify the RMN maintainers. // solhint-disable-next-line gas-struct-packing struct StaticConfig { - address linkToken; // ────────╮ Link token address - uint64 chainSelector; // ─────╯ Source chainSelector - uint96 maxFeeJuelsPerMsg; // ─╮ Maximum fee that can be charged for a message + uint64 chainSelector; // ─────╮ Source chainSelector address rmnProxy; // ─────────╯ Address of RMN proxy address nonceManager; // Address of the nonce manager address tokenAdminRegistry; // Token admin registry address @@ -81,95 +64,8 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre address feeAggregator; // Fee aggregator address } - /// @dev Struct to hold the fee token configuration for a token, same as the s_premiumMultiplierWeiPerEth but with - /// the token address included so that an array of these can be passed in the constructor and - /// applyPremiumMultiplierWeiPerEthUpdates to set the mapping - struct PremiumMultiplierWeiPerEthArgs { - address token; // // ───────────────────╮ Token address - uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. Should never be 0 so can be used as an isEnabled flag - } - - /// @dev Struct to hold the transfer fee configuration for token transfers - struct TokenTransferFeeConfig { - uint32 minFeeUSDCents; // ──────────╮ Minimum fee to charge per token transfer, multiples of 0.01 USD - uint32 maxFeeUSDCents; // │ Maximum fee to charge per token transfer, multiples of 0.01 USD - uint16 deciBps; // │ Basis points charged on token transfers, multiples of 0.1bps, or 1e-5 - uint32 destGasOverhead; // │ Gas charged to execute the token transfer on the destination chain - // │ Extra data availability bytes that are returned from the source pool and sent - uint32 destBytesOverhead; // │ to the destination pool. Must be >= Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - bool isEnabled; // ─────────────────╯ Whether this token has custom transfer fees - } - - /// @dev Struct to hold the token transfer fee configurations for a token, same as TokenTransferFeeConfig but with the token address included so - /// that an array of these can be passed in the TokenTransferFeeConfigArgs struct to set the mapping - struct TokenTransferFeeConfigSingleTokenArgs { - address token; // Token address - TokenTransferFeeConfig tokenTransferFeeConfig; // struct to hold the transfer fee configuration for token transfers - } - - /// @dev Struct to hold the token transfer fee configurations for a destination chain and a set of tokens. Same as TokenTransferFeeConfigSingleTokenArgs - /// but with the destChainSelector and an array of TokenTransferFeeConfigSingleTokenArgs included so that an array of these can be passed in the constructor - /// and the applyTokenTransferFeeConfigUpdates function - struct TokenTransferFeeConfigArgs { - uint64 destChainSelector; // Destination chain selector - TokenTransferFeeConfigSingleTokenArgs[] tokenTransferFeeConfigs; // Array of token transfer fee configurations - } - - /// @dev Struct to hold a pair of destination chain selector and token address so that an array of these can be passed in the - /// applyTokenTransferFeeConfigUpdates function to remove the token transfer fee configuration for a token - struct TokenTransferFeeConfigRemoveArgs { - uint64 destChainSelector; // ─╮ Destination chain selector - address token; // ────────────╯ Token address - } - - /// @dev Struct to hold the dynamic configs for a destination chain - struct DestChainDynamicConfig { - bool isEnabled; // ──────────────────────────╮ Whether this destination chain is enabled - uint16 maxNumberOfTokensPerMsg; // │ Maximum number of distinct ERC20 token transferred per message - uint32 maxDataBytes; // │ Maximum payload data size in bytes - uint32 maxPerMsgGasLimit; // │ Maximum gas limit for messages targeting EVMs - uint32 destGasOverhead; // │ Gas charged on top of the gasLimit to cover destination chain costs - uint16 destGasPerPayloadByte; // │ Destination chain gas charged for passing each byte of `data` payload to receiver - uint32 destDataAvailabilityOverheadGas; // | Extra data availability gas charged on top of the message, e.g. for OCR - uint16 destGasPerDataAvailabilityByte; // | Amount of gas to charge per byte of message data that needs availability - uint16 destDataAvailabilityMultiplierBps; // │ Multiplier for data availability gas, multiples of bps, or 0.0001 - // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token - uint16 defaultTokenFeeUSDCents; // │ Default token fee charged per token transfer - uint32 defaultTokenDestGasOverhead; // ──────╯ Default gas charged to execute the token transfer on the destination chain - uint32 defaultTokenDestBytesOverhead; // ────╮ Default extra data availability bytes charged per token transfer - uint64 defaultTxGasLimit; // │ Default gas limit for a tx - uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. - uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD - bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. - bytes4 chainFamilySelector; // ──────────────╯ Selector that identifies the destination chain's family. Used to determine the correct validations to perform for the dest chain. - } - - /// @dev Struct to hold the configs for a destination chain - struct DestChainConfig { - DestChainDynamicConfig dynamicConfig; // Dynamic configs for a destination chain - uint64 sequenceNumber; // The last used sequence number. This is zero in the case where no messages has been sent yet. - // 0 is not a valid sequence number for any real transaction. - /// @dev metadataHash is a lane-specific prefix for a message hash preimage which ensures global uniqueness - /// Ensures that 2 identical messages sent to 2 different lanes will have a distinct hash. - /// Must match the metadataHash used in computing leaf hashes offchain for the root committed in - /// the commitStore and i_metadataHash in the offRamp. - bytes32 metadataHash; - } - - /// @dev Struct to hold the dynamic configs, its destination chain selector. Same as DestChainConfig but with the destChainSelector so that an array of these - /// can be passed in the constructor and the applyDestChainConfigUpdates function - //solhint-disable gas-struct-packing - struct DestChainConfigArgs { - uint64 destChainSelector; // Destination chain selector - DestChainDynamicConfig dynamicConfig; // Struct to hold the configs for a destination chain - } - // STATIC CONFIG string public constant override typeAndVersion = "EVM2EVMMultiOnRamp 1.6.0-dev"; - /// @dev Maximum fee that can be charged for a message. This is a guard to prevent massively overcharging due to misconfiguation. - uint96 internal immutable i_maxFeeJuelsPerMsg; - /// @dev The link token address - address internal immutable i_linkToken; /// @dev The chain ID of the source chain that this contract is deployed to uint64 internal immutable i_chainSelector; /// @dev The address of the rmn proxy @@ -186,14 +82,10 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre /// @dev The config for the onRamp DynamicConfig internal s_dynamicConfig; - /// @dev The destination chain specific configs - mapping(uint64 destChainSelector => DestChainConfig destChainConfig) internal s_destChainConfig; - /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin - /// This should never be 0 once set, so it can be used as an isEnabled flag - mapping(address token => uint64 premiumMultiplierWeiPerEth) internal s_premiumMultiplierWeiPerEth; - /// @dev The token transfer fee config that can be set by the owner or fee admin - mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) internal - s_tokenTransferFeeConfig; + /// @dev Last used sequence number per destination chain. + /// This is zero in the case where no messages have been sent yet. + /// 0 is not a valid sequence number for any real transaction. + mapping(uint64 destChainSelector => uint64 sequenceNumber) internal s_destChainSequenceNumbers; // STATE /// @dev The amount of LINK available to pay NOPS @@ -201,31 +93,20 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre /// @dev The combined weight of all NOPs weights uint32 internal s_nopWeightsTotal; - constructor( - StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - DestChainConfigArgs[] memory destChainConfigArgs, - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs - ) { + constructor(StaticConfig memory staticConfig, DynamicConfig memory dynamicConfig) { if ( - staticConfig.linkToken == address(0) || staticConfig.chainSelector == 0 || staticConfig.rmnProxy == address(0) - || staticConfig.nonceManager == address(0) || staticConfig.tokenAdminRegistry == address(0) + staticConfig.chainSelector == 0 || staticConfig.rmnProxy == address(0) || staticConfig.nonceManager == address(0) + || staticConfig.tokenAdminRegistry == address(0) ) { revert InvalidConfig(); } - i_linkToken = staticConfig.linkToken; i_chainSelector = staticConfig.chainSelector; - i_maxFeeJuelsPerMsg = staticConfig.maxFeeJuelsPerMsg; i_rmnProxy = staticConfig.rmnProxy; i_nonceManager = staticConfig.nonceManager; i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; _setDynamicConfig(dynamicConfig); - _applyDestChainConfigUpdates(destChainConfigArgs); - _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, new TokenTransferFeeConfigRemoveArgs[](0)); } // ================================================================ @@ -236,7 +117,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre /// @param destChainSelector The destination chain selector /// @return the next sequence number to be used function getExpectedNextSequenceNumber(uint64 destChainSelector) external view returns (uint64) { - return s_destChainConfig[destChainSelector].sequenceNumber + 1; + return s_destChainSequenceNumbers[destChainSelector] + 1; } /// @inheritdoc IEVM2AnyOnRampClient @@ -246,240 +127,118 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre uint256 feeTokenAmount, address originalSender ) external returns (bytes32) { - DestChainConfig storage destChainConfig = s_destChainConfig[destChainSelector]; - Internal.EVM2AnyRampMessage memory newMessage = - _generateNewMessage(destChainConfig, destChainSelector, message, feeTokenAmount, originalSender); - - // Lock the tokens as last step. TokenPools may not always be trusted. - // There should be no state changes after external call to TokenPools. - for (uint256 i = 0; i < newMessage.tokenAmounts.length; ++i) { - Client.EVMTokenAmount memory tokenAndAmount = message.tokenAmounts[i]; - - if (tokenAndAmount.amount == 0) revert CannotSendZeroTokens(); - - IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); - // We don't have to check if it supports the pool version in a non-reverting way here because - // if we revert here, there is no effect on CCIP. Therefore we directly call the supportsInterface - // function and not through the ERC165Checker. - if (address(sourcePool) == address(0) || !sourcePool.supportsInterface(Pool.CCIP_POOL_V1)) { - revert UnsupportedToken(tokenAndAmount.token); - } - - Pool.LockOrBurnOutV1 memory poolReturnData = sourcePool.lockOrBurn( - Pool.LockOrBurnInV1({ - receiver: message.receiver, - remoteChainSelector: destChainSelector, - originalSender: originalSender, - amount: tokenAndAmount.amount, - localToken: tokenAndAmount.token - }) - ); - - // Since the DON has to pay for the extraData to be included on the destination chain, we cap the length of the - // extraData. This prevents gas bomb attacks on the NOPs. As destBytesOverhead accounts for both - // extraData and offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData. - if (poolReturnData.destPoolData.length > Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - if ( - poolReturnData.destPoolData.length - > s_tokenTransferFeeConfig[destChainSelector][tokenAndAmount.token].destBytesOverhead - ) { - revert SourceTokenDataTooLarge(tokenAndAmount.token); - } - } - - _validateDestFamilyAddress(destChainConfig.dynamicConfig.chainFamilySelector, poolReturnData.destTokenAddress); - - newMessage.tokenAmounts[i] = Internal.RampTokenAmount({ - sourcePoolAddress: abi.encode(sourcePool), - destTokenAddress: poolReturnData.destTokenAddress, - extraData: poolReturnData.destPoolData, - amount: tokenAndAmount.amount - }); - } - - // Hash only after the sourceTokenData has been set - newMessage.header.messageId = Internal._hash(newMessage, destChainConfig.metadataHash); - - // Emit message request - // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this - // event in the offchain code. - emit CCIPSendRequested(destChainSelector, newMessage); - return newMessage.header.messageId; - } - - /// @notice Helper function to relieve stack pressure from `forwardFromRouter` - /// @param destChainConfig The destination chain config storage pointer - /// @param destChainSelector The destination chain selector - /// @param message Message struct to send - /// @param feeTokenAmount Amount of fee tokens for payment - /// @param originalSender The original initiator of the CCIP request - function _generateNewMessage( - DestChainConfig storage destChainConfig, - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message, - uint256 feeTokenAmount, - address originalSender - ) internal returns (Internal.EVM2AnyRampMessage memory) { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); + // NOTE: assumes the message has already been validated through the getFee call // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. if (originalSender == address(0)) revert RouterMustSetOriginalSender(); // Router address may be zero intentionally to pause. if (msg.sender != s_dynamicConfig.router) revert MustBeCalledByRouter(); - if (!destChainConfig.dynamicConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); - - // Validate the message with various checks - uint256 numberOfTokens = message.tokenAmounts.length; - // TODO: optimization - consider removing this call, since the Router calls into getFee -> _validateMessage - _validateMessage(destChainSelector, message.data.length, numberOfTokens, message.receiver); - - // Only check token value if there are tokens - if (numberOfTokens > 0) { - address messageValidator = s_dynamicConfig.messageValidator; - if (messageValidator != address(0)) { - try IMessageInterceptor(messageValidator).onOutboundMessage(destChainSelector, message) {} - catch (bytes memory err) { - revert IMessageInterceptor.MessageValidationError(err); - } - } - } - uint256 msgFeeJuels; - // Convert feeToken to link if not already in link - if (message.feeToken == i_linkToken) { - msgFeeJuels = feeTokenAmount; - } else { - msgFeeJuels = - IPriceRegistry(s_dynamicConfig.priceRegistry).convertTokenAmount(message.feeToken, feeTokenAmount, i_linkToken); + address messageValidator = s_dynamicConfig.messageValidator; + if (messageValidator != address(0)) { + IMessageInterceptor(messageValidator).onOutboundMessage(destChainSelector, message); } - emit FeePaid(message.feeToken, msgFeeJuels); - - if (msgFeeJuels > i_maxFeeJuelsPerMsg) revert MessageFeeTooHigh(msgFeeJuels, i_maxFeeJuelsPerMsg); + // Convert message fee to juels and retrieve converted args + (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) = IPriceRegistry( + s_dynamicConfig.priceRegistry + ).processMessageArgs(destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs); - // NOTE: when supporting non-EVM chains, revisit this and parse non-EVM args - // Assumes strict ordering, unless the chain is of the EVM family and the extra args indicate out of order execution - uint64 nonce = 0; - if (!_parseEVMExtraArgsFromBytes(message.extraArgs, destChainConfig.dynamicConfig).allowOutOfOrderExecution) { - // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we - // may block ordered message nonces, which is not what we want. - nonce = INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender); - } + emit FeePaid(message.feeToken, msgFeeJuels); - Internal.EVM2AnyRampMessage memory rampMessage = Internal.EVM2AnyRampMessage({ + Internal.EVM2AnyRampMessage memory newMessage = Internal.EVM2AnyRampMessage({ header: Internal.RampMessageHeader({ // Should be generated after the message is complete messageId: "", sourceChainSelector: i_chainSelector, destChainSelector: destChainSelector, // We need the next available sequence number so we increment before we use the value - sequenceNumber: ++destChainConfig.sequenceNumber, - nonce: nonce + sequenceNumber: ++s_destChainSequenceNumbers[destChainSelector], + // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we + // may block ordered message nonces, which is not what we want. + nonce: isOutOfOrderExecution + ? 0 + : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender) }), sender: originalSender, data: message.data, - extraArgs: _convertParsedExtraArgs(message.extraArgs, destChainConfig.dynamicConfig), + extraArgs: message.extraArgs, receiver: message.receiver, feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, - tokenAmounts: new Internal.RampTokenAmount[](numberOfTokens) // should be populated after generation + // Should be populated via lock / burn pool calls + tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) }); - return rampMessage; - } - - /// @dev Parses extraArgs with dest chain config family tag validation, and re-encodes the args to the latest arguments version. - /// Used to generate an EVM2AnyRampMessage with the accurate representation of the parsed extraArgs. - /// @param extraArgs The extra args bytes - /// @param destChainDynamicConfig Dest chain config to validate against - /// @return encodedExtraArgs the parsed & encoded extra args - function _convertParsedExtraArgs( - bytes calldata extraArgs, - DestChainDynamicConfig memory destChainDynamicConfig - ) internal pure returns (bytes memory encodedExtraArgs) { - bytes4 chainFamilySelector = destChainDynamicConfig.chainFamilySelector; - if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { - return abi.encode(_parseEVMExtraArgsFromBytes(extraArgs, destChainDynamicConfig)); - } - // Invalid chain family selectors cannot be configured - ignore invalid cases - return encodedExtraArgs; - } - - /// @dev Convert the extra args bytes into a struct with validations against the dest chain config - /// @param extraArgs The extra args bytes - /// @param destChainDynamicConfig Dest chain config to validate against - /// @return EVMExtraArgs the extra args struct (latest version) - function _parseEVMExtraArgsFromBytes( - bytes calldata extraArgs, - DestChainDynamicConfig memory destChainDynamicConfig - ) internal pure returns (Client.EVMExtraArgsV2 memory) { - Client.EVMExtraArgsV2 memory evmExtraArgs = - _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, destChainDynamicConfig.defaultTxGasLimit); - - if (evmExtraArgs.gasLimit > uint256(destChainDynamicConfig.maxPerMsgGasLimit)) revert MessageGasLimitTooHigh(); - if (destChainDynamicConfig.enforceOutOfOrder && !evmExtraArgs.allowOutOfOrderExecution) { - revert ExtraArgOutOfOrderExecutionMustBeTrue(); + // Lock the tokens as last step. TokenPools may not always be trusted. + // There should be no state changes after external call to TokenPools. + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + newMessage.tokenAmounts[i] = + _lockOrBurnSingleToken(message.tokenAmounts[i], destChainSelector, message.receiver, originalSender); } - return evmExtraArgs; - } - - /// @dev Convert the extra args bytes into a struct - /// @param extraArgs The extra args bytes - /// @param defaultTxGasLimit default tx gas limit to use in the absence of extra args - /// @return EVMExtraArgs the extra args struct (latest version) - function _parseUnvalidatedEVMExtraArgsFromBytes( - bytes calldata extraArgs, - uint64 defaultTxGasLimit - ) private pure returns (Client.EVMExtraArgsV2 memory) { - if (extraArgs.length == 0) { - // If extra args are empty, generate default values - return Client.EVMExtraArgsV2({gasLimit: defaultTxGasLimit, allowOutOfOrderExecution: false}); - } + // Validate pool return data after it is populated (view function - no state changes) + IPriceRegistry(s_dynamicConfig.priceRegistry).validatePoolReturnData( + destChainSelector, newMessage.tokenAmounts, message.tokenAmounts + ); - bytes4 extraArgsTag = bytes4(extraArgs); - bytes memory argsData = extraArgs[4:]; + // Override extraArgs with latest version + newMessage.extraArgs = convertedExtraArgs; - if (extraArgsTag == Client.EVM_EXTRA_ARGS_V2_TAG) { - return abi.decode(argsData, (Client.EVMExtraArgsV2)); - } else if (extraArgsTag == Client.EVM_EXTRA_ARGS_V1_TAG) { - // EVMExtraArgsV1 originally included a second boolean (strict) field which has been deprecated. - // Clients may still include it but it will be ignored. - return Client.EVMExtraArgsV2({gasLimit: abi.decode(argsData, (uint256)), allowOutOfOrderExecution: false}); - } + // Hash only after all fields have been set + newMessage.header.messageId = Internal._hash( + newMessage, + // Metadata hash preimage to ensure global uniqueness, ensuring 2 identical messages sent to 2 different + // lanes will have a distinct hash. + keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))) + ); - revert InvalidExtraArgsTag(); + // Emit message request + // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this + // event in the offchain code. + emit CCIPSendRequested(destChainSelector, newMessage); + return newMessage.header.messageId; } - /// @notice Validate the forwarded message with various checks. - /// @dev This function can be called multiple times during a CCIPSend, - /// only common user-driven mistakes are validated here to minimize duplicate validation cost. - /// @param destChainSelector The destination chain selector. - /// @param dataLength The length of the data field of the message. - /// @param numberOfTokens The number of tokens to be sent. - function _validateMessage( + /// @notice Uses a pool to lock or burn a token + /// @param tokenAndAmount Token address and amount to lock or burn + /// @param destChainSelector Target dest chain selector of the message + /// @param receiver Message receiver + /// @param originalSender Message sender + /// @return rampTokenAndAmount Ramp token and amount data + function _lockOrBurnSingleToken( + Client.EVMTokenAmount memory tokenAndAmount, uint64 destChainSelector, - uint256 dataLength, - uint256 numberOfTokens, - bytes calldata receiver - ) internal view { - // Check that payload is formed correctly - DestChainDynamicConfig storage destChainDynamicConfig = s_destChainConfig[destChainSelector].dynamicConfig; - if (dataLength > uint256(destChainDynamicConfig.maxDataBytes)) { - revert MessageTooLarge(uint256(destChainDynamicConfig.maxDataBytes), dataLength); + bytes memory receiver, + address originalSender + ) internal returns (Internal.RampTokenAmount memory) { + if (tokenAndAmount.amount == 0) revert CannotSendZeroTokens(); + + IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); + // We don't have to check if it supports the pool version in a non-reverting way here because + // if we revert here, there is no effect on CCIP. Therefore we directly call the supportsInterface + // function and not through the ERC165Checker. + if (address(sourcePool) == address(0) || !sourcePool.supportsInterface(Pool.CCIP_POOL_V1)) { + revert UnsupportedToken(tokenAndAmount.token); } - if (numberOfTokens > uint256(destChainDynamicConfig.maxNumberOfTokensPerMsg)) revert UnsupportedNumberOfTokens(); - _validateDestFamilyAddress(destChainDynamicConfig.chainFamilySelector, receiver); - } + Pool.LockOrBurnOutV1 memory poolReturnData = sourcePool.lockOrBurn( + Pool.LockOrBurnInV1({ + receiver: receiver, + remoteChainSelector: destChainSelector, + originalSender: originalSender, + amount: tokenAndAmount.amount, + localToken: tokenAndAmount.token + }) + ); - /// @notice Validates that the destAddress matches the expected format of the family. - /// @param chainFamilySelector Tag to identify the target family - /// @param destAddress Dest address to validate - /// @dev precondition - assumes the family tag is correct and validated - function _validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) internal pure { - if (chainFamilySelector == Internal.CHAIN_FAMILY_SELECTOR_EVM) { - Internal._validateEVMAddress(destAddress); - } + // NOTE: pool data validations are outsourced to the PriceRegistry to handle family-specific logic handling + + return Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(sourcePool), + destTokenAddress: poolReturnData.destTokenAddress, + extraData: poolReturnData.destPoolData, + amount: tokenAndAmount.amount + }); } // ================================================================ @@ -491,9 +250,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre /// @return the configuration. function getStaticConfig() external view returns (StaticConfig memory) { return StaticConfig({ - linkToken: i_linkToken, chainSelector: i_chainSelector, - maxFeeJuelsPerMsg: i_maxFeeJuelsPerMsg, rmnProxy: i_rmnProxy, nonceManager: i_nonceManager, tokenAdminRegistry: i_tokenAdminRegistry @@ -521,9 +278,7 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre emit ConfigSet( StaticConfig({ - linkToken: i_linkToken, chainSelector: i_chainSelector, - maxFeeJuelsPerMsg: i_maxFeeJuelsPerMsg, rmnProxy: i_rmnProxy, nonceManager: i_nonceManager, tokenAdminRegistry: i_tokenAdminRegistry @@ -559,317 +314,9 @@ contract EVM2EVMMultiOnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCre uint64 destChainSelector, Client.EVM2AnyMessage calldata message ) external view returns (uint256 feeTokenAmount) { - DestChainDynamicConfig storage destChainDynamicConfig = s_destChainConfig[destChainSelector].dynamicConfig; - - if (!destChainDynamicConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); - - // Validate the message with various checks - _validateMessage(destChainSelector, message.data.length, message.tokenAmounts.length, message.receiver); - - uint64 premiumMultiplierWeiPerEth = s_premiumMultiplierWeiPerEth[message.feeToken]; - - // premiumMultiplierWeiPerEth should never be 0 so it can be used as an isEnabled flag - if (premiumMultiplierWeiPerEth == 0) revert NotAFeeToken(message.feeToken); - - (uint224 feeTokenPrice, uint224 packedGasPrice) = - IPriceRegistry(s_dynamicConfig.priceRegistry).getTokenAndGasPrices(message.feeToken, destChainSelector); - - // Calculate premiumFee in USD with 18 decimals precision first. - // If message-only and no token transfers, a flat network fee is charged. - // If there are token transfers, premiumFee is calculated from token transfer fee. - // If there are both token transfers and message, premiumFee is only calculated from token transfer fee. - uint256 premiumFee = 0; - uint32 tokenTransferGas = 0; - uint32 tokenTransferBytesOverhead = 0; - if (message.tokenAmounts.length > 0) { - (premiumFee, tokenTransferGas, tokenTransferBytesOverhead) = - _getTokenTransferCost(destChainSelector, message.feeToken, feeTokenPrice, message.tokenAmounts); - } else { - // Convert USD cents with 2 decimals to 18 decimals. - premiumFee = uint256(destChainDynamicConfig.networkFeeUSDCents) * 1e16; - } - - // Calculate data availability cost in USD with 36 decimals. Data availability cost exists on rollups that need to post - // transaction calldata onto another storage layer, e.g. Eth mainnet, incurring additional storage gas costs. - uint256 dataAvailabilityCost = 0; - // Only calculate data availability cost if data availability multiplier is non-zero. - // The multiplier should be set to 0 if destination chain does not charge data availability cost. - if (destChainDynamicConfig.destDataAvailabilityMultiplierBps > 0) { - dataAvailabilityCost = _getDataAvailabilityCost( - destChainSelector, - // Parse the data availability gas price stored in the higher-order 112 bits of the encoded gas price. - uint112(packedGasPrice >> Internal.GAS_PRICE_BITS), - message.data.length, - message.tokenAmounts.length, - tokenTransferBytesOverhead - ); - } - - // Calculate execution gas fee on destination chain in USD with 36 decimals. - // We add the message gas limit, the overhead gas, the gas of passing message data to receiver, and token transfer gas together. - // We then multiply this gas total with the gas multiplier and gas price, converting it into USD with 36 decimals. - // uint112(packedGasPrice) = executionGasPrice - - // TODO: revisit how generic this logic can be for non-EVM chains - - uint256 executionGasCost = destChainDynamicConfig.destGasOverhead - + (message.data.length * destChainDynamicConfig.destGasPerPayloadByte) + tokenTransferGas; - - // NOTE: when supporting non-EVM chains, revisit this and parse non-EVM args - executionGasCost += _parseEVMExtraArgsFromBytes(message.extraArgs, destChainDynamicConfig).gasLimit; - - uint256 executionCost = uint112(packedGasPrice) * executionGasCost * destChainDynamicConfig.gasMultiplierWeiPerEth; - - // Calculate number of fee tokens to charge. - // Total USD fee is in 36 decimals, feeTokenPrice is in 18 decimals USD for 1e18 smallest token denominations. - // Result of the division is the number of smallest token denominations. - return ((premiumFee * premiumMultiplierWeiPerEth) + executionCost + dataAvailabilityCost) / feeTokenPrice; - } - - /// @notice Returns the estimated data availability cost of the message. - /// @dev To save on gas, we use a single destGasPerDataAvailabilityByte value for both zero and non-zero bytes. - /// @param destChainSelector the destination chain selector. - /// @param dataAvailabilityGasPrice USD per data availability gas in 18 decimals. - /// @param messageDataLength length of the data field in the message. - /// @param numberOfTokens number of distinct token transfers in the message. - /// @param tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. - /// @return dataAvailabilityCostUSD36Decimal total data availability cost in USD with 36 decimals. - function _getDataAvailabilityCost( - uint64 destChainSelector, - uint112 dataAvailabilityGasPrice, - uint256 messageDataLength, - uint256 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) internal view returns (uint256 dataAvailabilityCostUSD36Decimal) { - // dataAvailabilityLengthBytes sums up byte lengths of fixed message fields and dynamic message fields. - // Fixed message fields do account for the offset and length slot of the dynamic fields. - uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; - - DestChainDynamicConfig storage destChainDynamicConfig = s_destChainConfig[destChainSelector].dynamicConfig; - // destDataAvailabilityOverheadGas is a separate config value for flexibility to be updated independently of message cost. - // Its value is determined by CCIP lane implementation, e.g. the overhead data posted for OCR. - uint256 dataAvailabilityGas = (dataAvailabilityLengthBytes * destChainDynamicConfig.destGasPerDataAvailabilityByte) - + destChainDynamicConfig.destDataAvailabilityOverheadGas; - - // dataAvailabilityGasPrice is in 18 decimals, destDataAvailabilityMultiplierBps is in 4 decimals - // We pad 14 decimals to bring the result to 36 decimals, in line with token bps and execution fee. - return ((dataAvailabilityGas * dataAvailabilityGasPrice) * destChainDynamicConfig.destDataAvailabilityMultiplierBps) - * 1e14; - } - - /// @notice Returns the token transfer cost parameters. - /// A basis point fee is calculated from the USD value of each token transfer. - /// For each individual transfer, this fee is between [minFeeUSD, maxFeeUSD]. - /// Total transfer fee is the sum of each individual token transfer fee. - /// @dev Assumes that tokenAmounts are validated to be listed tokens elsewhere. - /// @dev Splitting one token transfer into multiple transfers is discouraged, - /// as it will result in a transferFee equal or greater than the same amount aggregated/de-duped. - /// @param destChainSelector the destination chain selector. - /// @param feeToken address of the feeToken. - /// @param feeTokenPrice price of feeToken in USD with 18 decimals. - /// @param tokenAmounts token transfers in the message. - /// @return tokenTransferFeeUSDWei total token transfer bps fee in USD with 18 decimals. - /// @return tokenTransferGas total execution gas of the token transfers. - /// @return tokenTransferBytesOverhead additional token transfer data passed to destination, e.g. USDC attestation. - function _getTokenTransferCost( - uint64 destChainSelector, - address feeToken, - uint224 feeTokenPrice, - Client.EVMTokenAmount[] calldata tokenAmounts - ) internal view returns (uint256 tokenTransferFeeUSDWei, uint32 tokenTransferGas, uint32 tokenTransferBytesOverhead) { - uint256 numberOfTokens = tokenAmounts.length; - - for (uint256 i = 0; i < numberOfTokens; ++i) { - Client.EVMTokenAmount memory tokenAmount = tokenAmounts[i]; - - // Validate if the token is supported, do not calculate fee for unsupported tokens. - if (address(getPoolBySourceToken(destChainSelector, IERC20(tokenAmount.token))) == address(0)) { - revert UnsupportedToken(tokenAmount.token); - } - - TokenTransferFeeConfig memory transferFeeConfig = s_tokenTransferFeeConfig[destChainSelector][tokenAmount.token]; - - // If the token has no specific overrides configured, we use the global defaults. - if (!transferFeeConfig.isEnabled) { - DestChainDynamicConfig storage destChainDynamicConfig = s_destChainConfig[destChainSelector].dynamicConfig; - tokenTransferFeeUSDWei += uint256(destChainDynamicConfig.defaultTokenFeeUSDCents) * 1e16; - tokenTransferGas += destChainDynamicConfig.defaultTokenDestGasOverhead; - tokenTransferBytesOverhead += destChainDynamicConfig.defaultTokenDestBytesOverhead; - continue; - } - - uint256 bpsFeeUSDWei = 0; - // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token. - // Useful for when the PriceRegistry cannot return a valid price for the token. - if (transferFeeConfig.deciBps > 0) { - uint224 tokenPrice = 0; - if (tokenAmount.token != feeToken) { - tokenPrice = IPriceRegistry(s_dynamicConfig.priceRegistry).getValidatedTokenPrice(tokenAmount.token); - } else { - tokenPrice = feeTokenPrice; - } - - // Calculate token transfer value, then apply fee ratio - // ratio represents multiples of 0.1bps, or 1e-5 - bpsFeeUSDWei = (tokenPrice._calcUSDValueFromTokenAmount(tokenAmount.amount) * transferFeeConfig.deciBps) / 1e5; - } - - tokenTransferGas += transferFeeConfig.destGasOverhead; - tokenTransferBytesOverhead += transferFeeConfig.destBytesOverhead; - - // Bps fees should be kept within range of [minFeeUSD, maxFeeUSD]. - // Convert USD values with 2 decimals to 18 decimals. - uint256 minFeeUSDWei = uint256(transferFeeConfig.minFeeUSDCents) * 1e16; - if (bpsFeeUSDWei < minFeeUSDWei) { - tokenTransferFeeUSDWei += minFeeUSDWei; - continue; - } - - uint256 maxFeeUSDWei = uint256(transferFeeConfig.maxFeeUSDCents) * 1e16; - if (bpsFeeUSDWei > maxFeeUSDWei) { - tokenTransferFeeUSDWei += maxFeeUSDWei; - continue; - } - - tokenTransferFeeUSDWei += bpsFeeUSDWei; - } - - return (tokenTransferFeeUSDWei, tokenTransferGas, tokenTransferBytesOverhead); - } - - /// @notice Updates the destination chain specific config. - /// @param destChainConfigArgs Array of source chain specific configs. - function applyDestChainConfigUpdates(DestChainConfigArgs[] memory destChainConfigArgs) external onlyOwner { - _applyDestChainConfigUpdates(destChainConfigArgs); - } - - /// @notice Internal version of applyDestChainConfigUpdates. - function _applyDestChainConfigUpdates(DestChainConfigArgs[] memory destChainConfigArgs) internal { - for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { - DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[i]; - uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; - - // NOTE: when supporting non-EVM chains, update chainFamilySelector validations - if ( - destChainSelector == 0 || destChainConfigArg.dynamicConfig.defaultTxGasLimit == 0 - || destChainConfigArg.dynamicConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM - ) { - revert InvalidDestChainConfig(destChainSelector); - } - - DestChainConfig storage destChainConfig = s_destChainConfig[destChainSelector]; - - DestChainConfig memory newDestChainConfig = DestChainConfig({ - dynamicConfig: destChainConfigArg.dynamicConfig, - sequenceNumber: destChainConfig.sequenceNumber, - metadataHash: destChainConfig.metadataHash - }); - - destChainConfig.dynamicConfig = newDestChainConfig.dynamicConfig; - - if (destChainConfig.metadataHash == 0) { - newDestChainConfig.metadataHash = - keccak256(abi.encode(Internal.EVM_2_ANY_MESSAGE_HASH, i_chainSelector, destChainSelector, address(this))); - destChainConfig.metadataHash = newDestChainConfig.metadataHash; - - emit DestChainAdded(destChainSelector, destChainConfig); - } else { - if (destChainConfigArg.dynamicConfig.defaultTokenDestBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - revert InvalidDestBytesOverhead(address(0), destChainConfigArg.dynamicConfig.defaultTokenDestBytesOverhead); - } - - emit DestChainDynamicConfigUpdated(destChainSelector, destChainConfigArg.dynamicConfig); - } - } - } - - /// @notice Returns the destination chain config for given destination chain selector. - /// @param destChainSelector The destination chain selector. - /// @return The destination chain config. - function getDestChainConfig(uint64 destChainSelector) external view returns (DestChainConfig memory) { - return s_destChainConfig[destChainSelector]; - } - - /// @notice Gets the fee configuration for a token. - /// @param token The token to get the fee configuration for. - /// @return premiumMultiplierWeiPerEth The multiplier for destination chain specific premiums. - function getPremiumMultiplierWeiPerEth(address token) external view returns (uint64 premiumMultiplierWeiPerEth) { - return s_premiumMultiplierWeiPerEth[token]; - } - - /// @notice Sets the fee configuration for a token - /// @param premiumMultiplierWeiPerEthArgs Array of PremiumMultiplierWeiPerEthArgs structs. - function applyPremiumMultiplierWeiPerEthUpdates( - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs - ) external onlyOwner { - _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - } - - /// @dev Set the fee config. - /// @param premiumMultiplierWeiPerEthArgs The multiplier for destination chain specific premiums. - function _applyPremiumMultiplierWeiPerEthUpdates( - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs - ) internal { - for (uint256 i = 0; i < premiumMultiplierWeiPerEthArgs.length; ++i) { - address token = premiumMultiplierWeiPerEthArgs[i].token; - uint64 premiumMultiplierWeiPerEth = premiumMultiplierWeiPerEthArgs[i].premiumMultiplierWeiPerEth; - s_premiumMultiplierWeiPerEth[token] = premiumMultiplierWeiPerEth; - - emit PremiumMultiplierWeiPerEthUpdated(token, premiumMultiplierWeiPerEth); - } - } - - /// @notice Gets the transfer fee config for a given token. - /// @param destChainSelector The destination chain selector. - /// @param token The token address. - function getTokenTransferFeeConfig( - uint64 destChainSelector, - address token - ) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) { - return s_tokenTransferFeeConfig[destChainSelector][token]; - } - - /// @notice Sets the transfer fee config. - /// @dev only callable by the owner or admin. - function applyTokenTransferFeeConfigUpdates( - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs - ) external onlyOwner { - _applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs); - } - - /// @notice internal helper to set the token transfer fee config. - function _applyTokenTransferFeeConfigUpdates( - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, - TokenTransferFeeConfigRemoveArgs[] memory tokensToUseDefaultFeeConfigs - ) internal { - for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { - TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = tokenTransferFeeConfigArgs[i]; - uint64 destChainSelector = tokenTransferFeeConfigArg.destChainSelector; - - for (uint256 j = 0; j < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++j) { - TokenTransferFeeConfig memory tokenTransferFeeConfig = - tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].tokenTransferFeeConfig; - address token = tokenTransferFeeConfigArg.tokenTransferFeeConfigs[j].token; - - if (tokenTransferFeeConfig.destBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { - revert InvalidDestBytesOverhead(token, tokenTransferFeeConfig.destBytesOverhead); - } - - s_tokenTransferFeeConfig[destChainSelector][token] = tokenTransferFeeConfig; - - emit TokenTransferFeeConfigUpdated(destChainSelector, token, tokenTransferFeeConfig); - } - } + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); - // Remove the custom fee configs for the tokens that are in the tokensToUseDefaultFeeConfigs array - for (uint256 i = 0; i < tokensToUseDefaultFeeConfigs.length; ++i) { - uint64 destChainSelector = tokensToUseDefaultFeeConfigs[i].destChainSelector; - address token = tokensToUseDefaultFeeConfigs[i].token; - delete s_tokenTransferFeeConfig[destChainSelector][token]; - emit TokenTransferFeeConfigDeleted(destChainSelector, token); - } + return IPriceRegistry(s_dynamicConfig.priceRegistry).getValidatedFee(destChainSelector, message); } /// @notice Withdraws the outstanding fee token balances to the fee aggregator. diff --git a/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/contracts/src/v0.8/ccip/test/BaseTest.t.sol index b150ec892b..ee3f3e6fd4 100644 --- a/contracts/src/v0.8/ccip/test/BaseTest.t.sol +++ b/contracts/src/v0.8/ccip/test/BaseTest.t.sol @@ -25,7 +25,7 @@ contract BaseTest is Test { // Message info uint64 internal constant SOURCE_CHAIN_SELECTOR = 1; uint64 internal constant DEST_CHAIN_SELECTOR = 2; - uint64 internal constant GAS_LIMIT = 200_000; + uint32 internal constant GAS_LIMIT = 200_000; // Timing uint256 internal constant BLOCK_TIME = 1234567890; diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index a99fc0c77a..75de4db8c5 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -244,8 +244,6 @@ contract NonceManager_OnRampUpgrade is EVM2EVMMultiOnRampSetup { NonceManager.PreviousRampsArgs(DEST_CHAIN_SELECTOR, NonceManager.PreviousRamps(address(s_prevOnRamp), address(0))); s_outboundNonceManager.applyPreviousRampsUpdates(previousRamps); - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - (s_onRamp, s_metadataHash) = _deployOnRamp( SOURCE_CHAIN_SELECTOR, address(s_sourceRouter), address(s_outboundNonceManager), address(s_tokenAdminRegistry) ); 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 new file mode 100644 index 0000000000..5deeda6406 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Client} from "../../../libraries/Client.sol"; +import {Internal} from "../../../libraries/Internal.sol"; +import {EVM2EVMMultiOnRamp} from "../../../onRamp/EVM2EVMMultiOnRamp.sol"; +import {TokenPool} from "../../../pools/TokenPool.sol"; +import {EVM2EVMMultiOnRampSetup} from "../../onRamp/EVM2EVMMultiOnRampSetup.t.sol"; +import {FacadeClient} from "./FacadeClient.sol"; +import {ReentrantMaliciousTokenPool} from "./ReentrantMaliciousTokenPool.sol"; + +import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + +import {console} from "forge-std/console.sol"; + +/// @title MultiOnRampTokenPoolReentrancy +/// Attempts to perform a reentrancy exploit on Onramp with a malicious TokenPool +contract MultiOnRampTokenPoolReentrancy is EVM2EVMMultiOnRampSetup { + FacadeClient internal s_facadeClient; + ReentrantMaliciousTokenPool internal s_maliciousTokenPool; + IERC20 internal s_sourceToken; + IERC20 internal s_feeToken; + address internal immutable i_receiver = makeAddr("receiver"); + + function setUp() public virtual override { + EVM2EVMMultiOnRampSetup.setUp(); + + s_sourceToken = IERC20(s_sourceTokens[0]); + s_feeToken = IERC20(s_sourceTokens[0]); + + s_facadeClient = + 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) + ); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](1); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(s_destPoolBySourceToken[s_sourceTokens[0]]), + remoteTokenAddress: abi.encode(s_destTokens[0]), + allowed: true, + outboundRateLimiterConfig: getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: getInboundRateLimiterConfig() + }); + s_maliciousTokenPool.applyChainUpdates(chainUpdates); + s_sourcePoolByToken[address(s_sourceToken)] = address(s_maliciousTokenPool); + + Internal.PoolUpdate[] memory removes = new Internal.PoolUpdate[](1); + removes[0].token = address(s_sourceToken); + removes[0].pool = address(s_sourcePoolByToken[address(s_sourceToken)]); + Internal.PoolUpdate[] memory adds = new Internal.PoolUpdate[](1); + adds[0].token = address(s_sourceToken); + adds[0].pool = address(s_maliciousTokenPool); + + s_tokenAdminRegistry.setPool(address(s_sourceToken), address(s_maliciousTokenPool)); + + s_sourceToken.transfer(address(s_facadeClient), 1e18); + s_feeToken.transfer(address(s_facadeClient), 1e18); + } + + /// @dev This test was used to showcase a reentrancy exploit on OnRamp with malicious TokenPool. + /// How it worked: OnRamp used to construct EVM2Any messages after calling TokenPool's lockOrBurn. + /// This allowed the malicious TokenPool to break message sequencing expectations as follows: + /// Any user -> Facade -> 1st call to ccipSend -> pool’s lockOrBurn —> + /// (reenter)-> Facade -> 2nd call to ccipSend + /// In this case, Facade's second call would produce an EVM2Any msg with a lower sequence number. + /// The issue was fixed by moving state updates and event construction to before TokenPool calls. + /// This test is kept to verify message sequence expectations are not broken. + function test_OnRampTokenPoolReentrancy_Success() public { + uint256 amount = 1; + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0].token = address(s_sourceToken); + tokenAmounts[0].amount = amount; + + Client.EVM2AnyMessage memory message1 = Client.EVM2AnyMessage({ + receiver: abi.encode(i_receiver), + data: abi.encodePacked(uint256(1)), // message 1 contains data 1 + tokenAmounts: tokenAmounts, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), + feeToken: address(s_feeToken) + }); + + Client.EVM2AnyMessage memory message2 = Client.EVM2AnyMessage({ + receiver: abi.encode(i_receiver), + data: abi.encodePacked(uint256(2)), // message 2 contains data 2 + tokenAmounts: tokenAmounts, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), + feeToken: address(s_feeToken) + }); + + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message1); + assertGt(expectedFee, 0); + + // Outcome of a successful exploit: + // Message 1 event from OnRamp contains sequence/nonce 2, message 2 contains sequence/nonce 1 + // Internal.EVM2EVMMessage memory msgEvent1 = _messageToEvent(message1, 2, 2, expectedFee, address(s_facadeClient)); + // Internal.EVM2EVMMessage memory msgEvent2 = _messageToEvent(message2, 1, 1, expectedFee, address(s_facadeClient)); + + // vm.expectEmit(); + // emit CCIPSendRequested(msgEvent2); + // vm.expectEmit(); + // emit CCIPSendRequested(msgEvent1); + + // After issue is fixed, sequence now increments as expected + Internal.EVM2AnyRampMessage memory msgEvent1 = _messageToEvent(message1, 1, 1, expectedFee, address(s_facadeClient)); + Internal.EVM2AnyRampMessage memory msgEvent2 = _messageToEvent(message2, 2, 2, expectedFee, address(s_facadeClient)); + + vm.expectEmit(); + emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent2); + vm.expectEmit(); + emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent1); + + s_facadeClient.send(amount); + } +} diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index ad42c20d14..cbe8a35dce 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -240,7 +240,7 @@ contract MultiRampsE2E is EVM2EVMMultiOnRampSetup, EVM2EVMMultiOffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - uint256 gasLimit = abi.decode(msgEvent.extraArgs, (Client.EVMExtraArgsV2)).gasLimit; + uint256 gasLimit = s_priceRegistry.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit; return Internal.Any2EVMRampMessage({ header: Internal.RampMessageHeader({ diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol index 6261e6539b..0532697d64 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOnRampHelper.sol @@ -7,56 +7,6 @@ import {IgnoreContractSize} from "./IgnoreContractSize.sol"; contract EVM2EVMMultiOnRampHelper is EVM2EVMMultiOnRamp, IgnoreContractSize { constructor( StaticConfig memory staticConfig, - DynamicConfig memory dynamicConfig, - DestChainConfigArgs[] memory destChainConfigs, - PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, - TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs - ) - EVM2EVMMultiOnRamp( - staticConfig, - dynamicConfig, - destChainConfigs, - premiumMultiplierWeiPerEthArgs, - tokenTransferFeeConfigArgs - ) - {} - - function getDataAvailabilityCost( - uint64 destChainSelector, - uint112 dataAvailabilityGasPrice, - uint256 messageDataLength, - uint256 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) external view returns (uint256) { - return _getDataAvailabilityCost( - destChainSelector, dataAvailabilityGasPrice, messageDataLength, numberOfTokens, tokenTransferBytesOverhead - ); - } - - function getTokenTransferCost( - uint64 destChainSelector, - address feeToken, - uint224 feeTokenPrice, - Client.EVMTokenAmount[] calldata tokenAmounts - ) external view returns (uint256, uint32, uint32) { - return _getTokenTransferCost(destChainSelector, feeToken, feeTokenPrice, tokenAmounts); - } - - function parseEVMExtraArgsFromBytes( - bytes calldata extraArgs, - uint64 destChainSelector - ) external view returns (Client.EVMExtraArgsV2 memory) { - return _parseEVMExtraArgsFromBytes(extraArgs, s_destChainConfig[destChainSelector].dynamicConfig); - } - - function validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) external pure { - _validateDestFamilyAddress(chainFamilySelector, destAddress); - } - - function convertParsedExtraArgs( - bytes calldata extraArgs, - DestChainDynamicConfig memory destChainDynamicConfig - ) external pure returns (bytes memory encodedExtraArgs) { - return _convertParsedExtraArgs(extraArgs, destChainDynamicConfig); - } + DynamicConfig memory dynamicConfig + ) EVM2EVMMultiOnRamp(staticConfig, dynamicConfig) {} } diff --git a/contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol b/contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol new file mode 100644 index 0000000000..8524df12cc --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {PriceRegistry} from "../../PriceRegistry.sol"; +import {Client} from "../../libraries/Client.sol"; + +contract PriceRegistryHelper is PriceRegistry { + constructor( + StaticConfig memory staticConfig, + address[] memory priceUpdaters, + address[] memory feeTokens, + TokenPriceFeedUpdate[] memory tokenPriceFeeds, + TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs, + PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, + DestChainConfigArgs[] memory destChainConfigArgs + ) + PriceRegistry( + staticConfig, + priceUpdaters, + feeTokens, + tokenPriceFeeds, + tokenTransferFeeConfigArgs, + premiumMultiplierWeiPerEthArgs, + destChainConfigArgs + ) + {} + + function getDataAvailabilityCost( + uint64 destChainSelector, + uint112 dataAvailabilityGasPrice, + uint256 messageDataLength, + uint256 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) external view returns (uint256) { + return _getDataAvailabilityCost( + s_destChainConfigs[destChainSelector], + dataAvailabilityGasPrice, + messageDataLength, + numberOfTokens, + tokenTransferBytesOverhead + ); + } + + function getTokenTransferCost( + uint64 destChainSelector, + address feeToken, + uint224 feeTokenPrice, + Client.EVMTokenAmount[] calldata tokenAmounts + ) external view returns (uint256, uint32, uint32) { + return _getTokenTransferCost( + s_destChainConfigs[destChainSelector], destChainSelector, feeToken, feeTokenPrice, tokenAmounts + ); + } + + function parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + uint64 destChainSelector + ) external view returns (Client.EVMExtraArgsV2 memory) { + return _parseEVMExtraArgsFromBytes(extraArgs, s_destChainConfigs[destChainSelector]); + } + + function parseEVMExtraArgsFromBytes( + bytes calldata extraArgs, + DestChainConfig memory destChainConfig + ) external pure returns (Client.EVMExtraArgsV2 memory) { + return _parseEVMExtraArgsFromBytes(extraArgs, destChainConfig); + } + + function validateDestFamilyAddress(bytes4 chainFamilySelector, bytes memory destAddress) external pure { + _validateDestFamilyAddress(chainFamilySelector, destAddress); + } +} diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol index b4375adc5b..87db031951 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol @@ -26,7 +26,7 @@ contract MockCCIPRouter is IRouter, IRouterClient { event MsgExecuted(bool success, bytes retData, uint256 gasUsed); uint16 public constant GAS_FOR_CALL_EXACT_CHECK = 5_000; - uint64 public constant DEFAULT_GAS_LIMIT = 200_000; + uint32 public constant DEFAULT_GAS_LIMIT = 200_000; uint256 internal s_mockFeeTokenAmount; //use setFee() to change to non-zero to test fees diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol index 2cc1de1ddd..bc7fac95be 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRamp.t.sol @@ -20,9 +20,7 @@ import "./EVM2EVMMultiOnRampSetup.t.sol"; contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { function test_Constructor_Success() public { EVM2EVMMultiOnRamp.StaticConfig memory staticConfig = EVM2EVMMultiOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], chainSelector: SOURCE_CHAIN_SELECTOR, - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, rmnProxy: address(s_mockRMN), nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) @@ -30,98 +28,35 @@ contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { EVM2EVMMultiOnRamp.DynamicConfig memory dynamicConfig = _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)); - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - vm.expectEmit(); emit EVM2EVMMultiOnRamp.ConfigSet(staticConfig, dynamicConfig); - // We ignore the DestChainConfig values as metadataHash is reliant on contract address. - vm.expectEmit(true, false, false, false); - emit EVM2EVMMultiOnRamp.DestChainAdded( - DEST_CHAIN_SELECTOR, - EVM2EVMMultiOnRamp.DestChainConfig({ - dynamicConfig: destChainConfigArg.dynamicConfig, - sequenceNumber: 0, - metadataHash: "" - }) - ); - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthUpdated( - s_premiumMultiplierWeiPerEthArgs[0].token, s_premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth - ); - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthUpdated( - s_premiumMultiplierWeiPerEthArgs[1].token, s_premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth - ); _deployOnRamp( SOURCE_CHAIN_SELECTOR, address(s_sourceRouter), address(s_outboundNonceManager), address(s_tokenAdminRegistry) ); - EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig = EVM2EVMMultiOnRamp.DestChainConfig({ - dynamicConfig: destChainConfigArg.dynamicConfig, - sequenceNumber: 0, - metadataHash: keccak256( - abi.encode( - Internal.EVM_2_ANY_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArg.destChainSelector, address(s_onRamp) - ) - ) - }); - EVM2EVMMultiOnRamp.StaticConfig memory gotStaticConfig = s_onRamp.getStaticConfig(); _assertStaticConfigsEqual(staticConfig, gotStaticConfig); EVM2EVMMultiOnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); _assertDynamicConfigsEqual(dynamicConfig, gotDynamicConfig); - EVM2EVMMultiOnRamp.DestChainConfig memory gotDestChainConfig = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR); - _assertDestChainConfigsEqual(expectedDestChainConfig, gotDestChainConfig); - - uint64 gotFeeTokenConfig0 = s_onRamp.getPremiumMultiplierWeiPerEth(s_premiumMultiplierWeiPerEthArgs[0].token); - assertEq(s_premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, gotFeeTokenConfig0); - - uint64 gotFeeTokenConfig1 = s_onRamp.getPremiumMultiplierWeiPerEth(s_premiumMultiplierWeiPerEthArgs[1].token); - assertEq(s_premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, gotFeeTokenConfig1); - // Initial values assertEq("EVM2EVMMultiOnRamp 1.6.0-dev", s_onRamp.typeAndVersion()); assertEq(OWNER, s_onRamp.owner()); - assertEq(1, s_onRamp.getExpectedNextSequenceNumber(destChainConfigArg.destChainSelector)); - } - - function test_Constructor_InvalidConfigLinkTokenEqAddressZero_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - new EVM2EVMMultiOnRampHelper( - EVM2EVMMultiOnRamp.StaticConfig({ - linkToken: address(0), - chainSelector: SOURCE_CHAIN_SELECTOR, - maxFeeJuelsPerMsg: MAX_NOP_FEES_JUELS, - rmnProxy: address(s_mockRMN), - nonceManager: address(s_outboundNonceManager), - tokenAdminRegistry: address(s_tokenAdminRegistry) - }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), - _generateDestChainConfigArgs(), - s_premiumMultiplierWeiPerEthArgs, - s_tokenTransferFeeConfigArgs - ); + assertEq(1, s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR)); } - function test_Constructor_InvalidConfigLinkChainSelectorEqZero_Revert() public { + function test_Constructor_InvalidConfigChainSelectorEqZero_Revert() public { vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); new EVM2EVMMultiOnRampHelper( EVM2EVMMultiOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], chainSelector: 0, - maxFeeJuelsPerMsg: MAX_NOP_FEES_JUELS, rmnProxy: address(s_mockRMN), nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), - _generateDestChainConfigArgs(), - s_premiumMultiplierWeiPerEthArgs, - s_tokenTransferFeeConfigArgs + _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) ); } @@ -129,17 +64,12 @@ contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); s_onRamp = new EVM2EVMMultiOnRampHelper( EVM2EVMMultiOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], chainSelector: SOURCE_CHAIN_SELECTOR, - maxFeeJuelsPerMsg: MAX_NOP_FEES_JUELS, rmnProxy: address(0), nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), - _generateDestChainConfigArgs(), - s_premiumMultiplierWeiPerEthArgs, - s_tokenTransferFeeConfigArgs + _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) ); } @@ -147,17 +77,12 @@ contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); new EVM2EVMMultiOnRampHelper( EVM2EVMMultiOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], chainSelector: SOURCE_CHAIN_SELECTOR, - maxFeeJuelsPerMsg: MAX_NOP_FEES_JUELS, rmnProxy: address(s_mockRMN), nonceManager: address(0), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), - _generateDestChainConfigArgs(), - s_premiumMultiplierWeiPerEthArgs, - s_tokenTransferFeeConfigArgs + _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) ); } @@ -165,179 +90,13 @@ contract EVM2EVMMultiOnRamp_constructor is EVM2EVMMultiOnRampSetup { vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); new EVM2EVMMultiOnRampHelper( EVM2EVMMultiOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], chainSelector: SOURCE_CHAIN_SELECTOR, - maxFeeJuelsPerMsg: MAX_NOP_FEES_JUELS, rmnProxy: address(s_mockRMN), nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(0) }), - _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), - _generateDestChainConfigArgs(), - s_premiumMultiplierWeiPerEthArgs, - s_tokenTransferFeeConfigArgs - ); - } -} - -contract EVM2EVMMultiOnRamp_applyDestChainConfigUpdates is EVM2EVMMultiOnRampSetup { - function test_Fuzz_applyDestChainConfigUpdates_Success( - EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArgs - ) public { - vm.assume(destChainConfigArgs.destChainSelector != 0); - vm.assume(destChainConfigArgs.dynamicConfig.defaultTxGasLimit != 0); - destChainConfigArgs.dynamicConfig.defaultTokenDestBytesOverhead = uint32( - bound( - destChainConfigArgs.dynamicConfig.defaultTokenDestBytesOverhead, - Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, - type(uint32).max - ) - ); - destChainConfigArgs.dynamicConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - - bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; - - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory newDestChainConfigArgs = - new EVM2EVMMultiOnRamp.DestChainConfigArgs[](1); - newDestChainConfigArgs[0] = destChainConfigArgs; - EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig = EVM2EVMMultiOnRamp.DestChainConfig({ - dynamicConfig: destChainConfigArgs.dynamicConfig, - sequenceNumber: 0, - metadataHash: keccak256( - abi.encode( - Internal.EVM_2_ANY_MESSAGE_HASH, SOURCE_CHAIN_SELECTOR, destChainConfigArgs.destChainSelector, address(s_onRamp) - ) - ) - }); - - if (isNewChain) { - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.DestChainAdded(destChainConfigArgs.destChainSelector, expectedDestChainConfig); - } else { - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.DestChainDynamicConfigUpdated( - destChainConfigArgs.destChainSelector, expectedDestChainConfig.dynamicConfig - ); - } - - s_onRamp.applyDestChainConfigUpdates(newDestChainConfigArgs); - - _assertDestChainConfigsEqual( - expectedDestChainConfig, s_onRamp.getDestChainConfig(destChainConfigArgs.destChainSelector) - ); - } - - function test_applyDestChainConfigUpdates_Success() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = - new EVM2EVMMultiOnRamp.DestChainConfigArgs[](2); - destChainConfigArgs[0] = _generateDestChainConfigArgs()[0]; - destChainConfigArgs[0].dynamicConfig.isEnabled = false; - destChainConfigArgs[1] = _generateDestChainConfigArgs()[0]; - destChainConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; - - EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig0 = EVM2EVMMultiOnRamp.DestChainConfig({ - dynamicConfig: destChainConfigArgs[0].dynamicConfig, - sequenceNumber: 0, - metadataHash: keccak256( - abi.encode( - Internal.EVM_2_ANY_MESSAGE_HASH, - SOURCE_CHAIN_SELECTOR, - destChainConfigArgs[0].destChainSelector, - address(s_onRamp) - ) - ) - }); - - EVM2EVMMultiOnRamp.DestChainConfig memory expectedDestChainConfig1 = EVM2EVMMultiOnRamp.DestChainConfig({ - dynamicConfig: destChainConfigArgs[1].dynamicConfig, - sequenceNumber: 0, - metadataHash: keccak256( - abi.encode( - Internal.EVM_2_ANY_MESSAGE_HASH, - SOURCE_CHAIN_SELECTOR, - destChainConfigArgs[1].destChainSelector, - address(s_onRamp) - ) - ) - }); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.DestChainDynamicConfigUpdated(DEST_CHAIN_SELECTOR, expectedDestChainConfig0.dynamicConfig); - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.DestChainAdded(DEST_CHAIN_SELECTOR + 1, expectedDestChainConfig1); - - vm.recordLogs(); - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - - EVM2EVMMultiOnRamp.DestChainConfig memory gotDestChainConfig0 = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR); - EVM2EVMMultiOnRamp.DestChainConfig memory gotDestChainConfig1 = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); - - assertEq(vm.getRecordedLogs().length, 2); - _assertDestChainConfigsEqual(expectedDestChainConfig0, gotDestChainConfig0); - _assertDestChainConfigsEqual(expectedDestChainConfig1, gotDestChainConfig1); - } - - function test_applyDestChainConfigUpdatesZeroIntput() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = - new EVM2EVMMultiOnRamp.DestChainConfigArgs[](0); - - vm.recordLogs(); - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainSelector = 0; - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.dynamicConfig.defaultTxGasLimit = 0; - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) - ); - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_InvalidDestBytesOverhead_Revert() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.dynamicConfig.defaultTokenDestBytesOverhead = uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1); - - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMMultiOnRamp.InvalidDestBytesOverhead.selector, - address(0), - destChainConfigArg.dynamicConfig.defaultTokenDestBytesOverhead - ) - ); - - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - } - - function test_InvalidChainFamilySelector_Revert() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - EVM2EVMMultiOnRamp.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.dynamicConfig.chainFamilySelector = bytes4(uint32(1)); - - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + _generateDynamicMultiOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)) ); - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); } } @@ -392,13 +151,9 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { uint256 feeAmount = 1234567890; IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - Client.EVM2AnyMessage memory expectedMessage = _generateEmptyMessage(); - expectedMessage.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})); vm.expectEmit(); // We expect the message to be emitted with strict = false. - emit EVM2EVMMultiOnRamp.CCIPSendRequested( - DEST_CHAIN_SELECTOR, _messageToEvent(expectedMessage, 1, 1, feeAmount, OWNER) - ); + emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } @@ -443,50 +198,12 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_Fuzz_EnforceOutOfOrder(bool enforce, bool allowOutOfOrderExecution) public { - // Update dynamic config to enforce allowOutOfOrderExecution = defaultVal. - vm.stopPrank(); - vm.startPrank(OWNER); - - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - destChainConfigArgs[0].dynamicConfig.enforceOutOfOrder = enforce; - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - - vm.stopPrank(); - - vm.startPrank(address(s_sourceRouter)); - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = abi.encodeWithSelector( - Client.EVM_EXTRA_ARGS_V2_TAG, - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: allowOutOfOrderExecution}) - ); - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - - if (enforce) { - // If enforcement is on, only true should be allowed. - if (allowOutOfOrderExecution) { - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } else { - vm.expectRevert(EVM2EVMMultiOnRamp.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - } else { - // no enforcement should allow any value. - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); - } - } - function test_ShouldIncrementSeqNumAndNonce_Success() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); for (uint64 i = 1; i < 4; ++i) { uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberBefore = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).sequenceNumber; + uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; vm.expectEmit(); emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); @@ -494,7 +211,7 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberAfter = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).sequenceNumber; + uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; assertEq(nonceAfter, nonceBefore + 1); assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); } @@ -508,7 +225,7 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { for (uint64 i = 1; i < 4; ++i) { uint64 nonceBefore = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberBefore = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).sequenceNumber; + uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; vm.expectEmit(); emit EVM2EVMMultiOnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); @@ -516,7 +233,7 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); uint64 nonceAfter = s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER); - uint64 sequenceNumberAfter = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).sequenceNumber; + uint64 sequenceNumberAfter = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; assertEq(nonceAfter, nonceBefore); assertEq(sequenceNumberAfter, sequenceNumberBefore + 1); } @@ -625,12 +342,6 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, OWNER); - } - function test_Permissions_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); @@ -643,24 +354,6 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); } - function test_MessageTooLarge_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.data = new bytes(MAX_DATA_SIZE + 1); - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length) - ); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, STRANGER); - } - - function test_TooManyTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 tooMany = MAX_TOKENS_LENGTH + 1; - message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); - vm.expectRevert(EVM2EVMMultiOnRamp.UnsupportedNumberOfTokens.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, STRANGER); - } - function test_MessageValidationError_Revert() public { _enableOutboundMessageValidator(); @@ -674,10 +367,7 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_outboundMessageValidator.setMessageIdValidationState(keccak256(abi.encode(message)), true); vm.expectRevert( - abi.encodeWithSelector( - IMessageInterceptor.MessageValidationError.selector, - abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) - ) + abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) ); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); @@ -715,64 +405,27 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } - // Asserts gasLimit must be <=maxGasLimit - function test_MessageGasLimitTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.MessageGasLimitTooHigh.selector)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); - } - - function test_InvalidAddressEncodePacked_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encodePacked(address(234)); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 1, OWNER); - } - - function test_InvalidEVMAddress_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.receiver = abi.encode(type(uint208).max); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 1, OWNER); - } - - // We disallow sending to addresses 0-9. - function test_ZeroAddressReceiver_Revert() public { + function test_forwardFromRouter_UnsupportedToken_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.tokenAmounts = new Client.EVMTokenAmount[](1); + message.tokenAmounts[0].amount = 1; + message.tokenAmounts[0].token = address(1); - for (uint160 i = 0; i < 10; ++i) { - message.receiver = abi.encode(address(i)); - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); + vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.UnsupportedToken.selector, message.tokenAmounts[0].token)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 1, OWNER); - } + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } function test_MesssageFeeTooHigh_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + abi.encodeWithSelector(PriceRegistry.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) ); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); } - function test_InvalidChainSelector_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - - uint64 wrongChainSelector = DEST_CHAIN_SELECTOR + 1; - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.DestinationChainNotEnabled.selector, wrongChainSelector)); - - s_onRamp.forwardFromRouter(wrongChainSelector, message, 1, OWNER); - } - function test_SourceTokenDataTooLarge_Revert() public { address sourceETH = s_sourceTokens[1]; vm.stopPrank(); @@ -817,16 +470,16 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1)); vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.SourceTokenDataTooLarge.selector, sourceETH)); + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); // Set token config to allow larger data vm.startPrank(OWNER); - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = EVM2EVMMultiOnRamp + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry .TokenTransferFeeConfig({ minFeeUSDCents: 1, maxFeeUSDCents: 0, @@ -835,8 +488,8 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, isEnabled: true }); - s_onRamp.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](0) + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) ); vm.startPrank(address(s_sourceRouter)); @@ -847,54 +500,58 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { newPool.setSourceTokenData(new bytes(uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32 + 1)); vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.SourceTokenDataTooLarge.selector, sourceETH)); + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } +} - function test_InvalidEVMAddressDestToken_Revert() public { - address sourceETH = s_sourceTokens[1]; - vm.stopPrank(); - vm.startPrank(OWNER); - - MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC677(sourceETH), new address[](0), address(s_mockRMN), address(s_sourceRouter) - ); - BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); - deal(address(sourceETH), address(newPool), type(uint256).max); +contract EVM2EVMMultiOnRamp_getSupportedTokens is EVM2EVMMultiOnRampSetup { + function test_GetSupportedTokens_Revert() public { + vm.expectRevert(EVM2EVMMultiOnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); + s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); + } +} - // Add TokenPool to OnRamp - s_tokenAdminRegistry.setPool(sourceETH, address(newPool)); +contract EVM2EVMMultiOnRamp_getFee is EVM2EVMMultiOnRampSetup { + using USDPriceWith18Decimals for uint224; - bytes memory nonEvmAddress = abi.encode(type(uint208).max); + function test_EmptyMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - // 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), - remoteTokenAddress: nonEvmAddress, - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - newPool.applyChainUpdates(chainUpdates); + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = testTokens[i]; - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(address(sourceETH), 1000); + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); - vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + assertEq(expectedFeeAmount, feeAmount); + } } - function test_forwardFromRouter_UnsupportedToken_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.tokenAmounts = new Client.EVMTokenAmount[](1); - message.tokenAmounts[0].amount = 1; - message.tokenAmounts[0].token = address(1); + function test_SingleTokenMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.UnsupportedToken.selector, message.tokenAmounts[0].token)); + uint256 tokenAmount = 10000e18; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + message.feeToken = testTokens[i]; - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + assertEq(expectedFeeAmount, feeAmount); + } + } + + // Reverts + + function test_Unhealthy_Revert() public { + s_mockRMN.setGlobalCursed(true); + vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); + s_onRamp.getFee(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); } function test_EnforceOutOfOrder_Revert() public { @@ -902,755 +559,52 @@ contract EVM2EVMMultiOnRamp_forwardFromRouter is EVM2EVMMultiOnRampSetup { vm.stopPrank(); vm.startPrank(OWNER); - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - destChainConfigArgs[0].dynamicConfig.enforceOutOfOrder = true; - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); vm.stopPrank(); - vm.startPrank(address(s_sourceRouter)); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); // Empty extraArgs to should revert since it enforceOutOfOrder is true. message.extraArgs = ""; - uint256 feeAmount = 1234567890; - IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - vm.expectRevert(EVM2EVMMultiOnRamp.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); + vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); } } -contract EVM2EVMMultiOnRamp_getFeeSetup is EVM2EVMMultiOnRampSetup { - uint224 internal s_feeTokenPrice; - uint224 internal s_wrappedTokenPrice; - uint224 internal s_customTokenPrice; - - address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); +contract EVM2EVMMultiOnRamp_setDynamicConfig is EVM2EVMMultiOnRampSetup { + function test_SetDynamicConfig_Success() public { + EVM2EVMMultiOnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); + EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ + router: address(2134), + priceRegistry: address(23423), + messageValidator: makeAddr("messageValidator"), + feeAggregator: FEE_AGGREGATOR + }); - function setUp() public virtual override { - super.setUp(); + vm.expectEmit(); + emit EVM2EVMMultiOnRamp.ConfigSet(staticConfig, newConfig); - // Add additional pool addresses for test tokens to mark them as supported - s_tokenAdminRegistry.proposeAdministrator(s_sourceRouter.getWrappedNative(), OWNER); - s_tokenAdminRegistry.acceptAdminRole(s_sourceRouter.getWrappedNative()); - s_tokenAdminRegistry.proposeAdministrator(CUSTOM_TOKEN, OWNER); - s_tokenAdminRegistry.acceptAdminRole(CUSTOM_TOKEN); + s_onRamp.setDynamicConfig(newConfig); - LockReleaseTokenPool wrappedNativePool = new LockReleaseTokenPool( - IERC20(s_sourceRouter.getWrappedNative()), new address[](0), address(s_mockRMN), true, address(s_sourceRouter) - ); + EVM2EVMMultiOnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); + assertEq(newConfig.router, gotDynamicConfig.router); + assertEq(newConfig.priceRegistry, gotDynamicConfig.priceRegistry); + } - TokenPool.ChainUpdate[] memory wrappedNativeChainUpdate = new TokenPool.ChainUpdate[](1); - wrappedNativeChainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() - }); - wrappedNativePool.applyChainUpdates(wrappedNativeChainUpdate); - s_tokenAdminRegistry.setPool(s_sourceRouter.getWrappedNative(), address(wrappedNativePool)); + // Reverts - LockReleaseTokenPool customPool = new LockReleaseTokenPool( - IERC20(CUSTOM_TOKEN), new address[](0), address(s_mockRMN), true, address(s_sourceRouter) - ); - TokenPool.ChainUpdate[] memory customChainUpdate = new TokenPool.ChainUpdate[](1); - customChainUpdate[0] = TokenPool.ChainUpdate({ - remoteChainSelector: DEST_CHAIN_SELECTOR, - remotePoolAddress: abi.encode(s_destTokenPool), - remoteTokenAddress: abi.encode(s_destToken), - allowed: true, - outboundRateLimiterConfig: getOutboundRateLimiterConfig(), - inboundRateLimiterConfig: getInboundRateLimiterConfig() + function test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() public { + EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ + router: address(2134), + priceRegistry: address(0), + feeAggregator: FEE_AGGREGATOR, + messageValidator: makeAddr("messageValidator") }); - customPool.applyChainUpdates(customChainUpdate); - s_tokenAdminRegistry.setPool(CUSTOM_TOKEN, address(customPool)); - - s_feeTokenPrice = s_sourceTokenPrices[0]; - s_wrappedTokenPrice = s_sourceTokenPrices[2]; - s_customTokenPrice = CUSTOM_TOKEN_PRICE; - - // Ensure the self-serve token is set up on the admin registry - vm.mockCall( - address(s_tokenAdminRegistry), - abi.encodeWithSelector(ITokenAdminRegistry.getPool.selector, s_selfServeTokenDefaultPricing), - abi.encode(makeAddr("self-serve-pool")) - ); - } - - function calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { - return (tokenPrice * tokenAmount) / 1e18; - } - function applyBpsRatio(uint256 tokenAmount, uint16 ratio) internal pure returns (uint256) { - return (tokenAmount * ratio) / 1e5; - } - - function configUSDCentToWei(uint256 usdCent) internal pure returns (uint256) { - return usdCent * 1e16; - } -} - -contract EVM2EVMMultiOnRamp_getDataAvailabilityCost is EVM2EVMMultiOnRamp_getFeeSetup { - function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { - uint256 dataAvailabilityCostUSD = - s_onRamp.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory destChainDynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - - uint256 dataAvailabilityGas = destChainDynamicConfig.destDataAvailabilityOverheadGas - + destChainDynamicConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; - uint256 expectedDataAvailabilityCostUSD = USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas - * destChainDynamicConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - - // Test that the cost is destnation chain specific - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = _generateDestChainConfigArgs(); - destChainConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR + 1; - destChainConfigArgs[0].dynamicConfig.destDataAvailabilityOverheadGas = - destChainDynamicConfig.destDataAvailabilityOverheadGas * 2; - destChainConfigArgs[0].dynamicConfig.destGasPerDataAvailabilityByte = - destChainDynamicConfig.destGasPerDataAvailabilityByte * 2; - destChainConfigArgs[0].dynamicConfig.destDataAvailabilityMultiplierBps = - destChainDynamicConfig.destDataAvailabilityMultiplierBps * 2; - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - - destChainDynamicConfig = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR + 1).dynamicConfig; - uint256 dataAvailabilityCostUSD2 = - s_onRamp.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - dataAvailabilityGas = destChainDynamicConfig.destDataAvailabilityOverheadGas - + destChainDynamicConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; - expectedDataAvailabilityCostUSD = USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas - * destChainDynamicConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD2); - assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); - } - - function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { - uint256 dataAvailabilityCostUSD = - s_onRamp.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory destChainDynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - - uint256 dataAvailabilityLengthBytes = - Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + 100 + (5 * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; - uint256 dataAvailabilityGas = destChainDynamicConfig.destDataAvailabilityOverheadGas - + destChainDynamicConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas - * destChainDynamicConfig.destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } - - function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { - uint256 dataAvailabilityCostUSD = s_onRamp.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - - assertEq(dataAvailabilityCostUSD, 0); - } - - function test_Fuzz_ZeroDataAvailabilityGasPriceAlwaysCalculatesZeroDataAvailabilityCost_Success( - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public view { - uint256 dataAvailabilityCostUSD = s_onRamp.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, 0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead - ); - - assertEq(0, dataAvailabilityCostUSD); - } - - function test_Fuzz_CalculateDataAvailabilityCost_Success( - uint64 destChainSelector, - uint32 destDataAvailabilityOverheadGas, - uint16 destGasPerDataAvailabilityByte, - uint16 destDataAvailabilityMultiplierBps, - uint112 dataAvailabilityGasPrice, - uint64 messageDataLength, - uint32 numberOfTokens, - uint32 tokenTransferBytesOverhead - ) public { - vm.assume(destChainSelector != 0); - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = - new EVM2EVMMultiOnRamp.DestChainConfigArgs[](1); - EVM2EVMMultiOnRamp.DestChainConfig memory destChainConfig = s_onRamp.getDestChainConfig(destChainSelector); - destChainConfigArgs[0] = EVM2EVMMultiOnRamp.DestChainConfigArgs({ - destChainSelector: destChainSelector, - dynamicConfig: destChainConfig.dynamicConfig - }); - destChainConfigArgs[0].dynamicConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; - destChainConfigArgs[0].dynamicConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; - destChainConfigArgs[0].dynamicConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; - destChainConfigArgs[0].dynamicConfig.defaultTxGasLimit = GAS_LIMIT; - destChainConfigArgs[0].dynamicConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - - uint256 dataAvailabilityCostUSD = s_onRamp.getDataAvailabilityCost( - destChainConfigArgs[0].destChainSelector, - dataAvailabilityGasPrice, - messageDataLength, - numberOfTokens, - tokenTransferBytesOverhead - ); - - uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength - + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; - - uint256 dataAvailabilityGas = - destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; - uint256 expectedDataAvailabilityCostUSD = - dataAvailabilityGasPrice * dataAvailabilityGas * destDataAvailabilityMultiplierBps * 1e14; - - assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); - } -} - -contract EVM2EVMMultiOnRamp_getSupportedTokens is EVM2EVMMultiOnRampSetup { - function test_GetSupportedTokens_Revert() public { - vm.expectRevert(EVM2EVMMultiOnRamp.GetSupportedTokensFunctionalityRemovedCheckAdminRegistry.selector); - s_onRamp.getSupportedTokens(DEST_CHAIN_SELECTOR); - } -} - -contract EVM2EVMMultiOnRamp_getFee is EVM2EVMMultiOnRamp_getFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_EmptyMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.feeToken = testTokens[i]; - uint64 premiumMultiplierWeiPerEth = s_onRamp.getPremiumMultiplierWeiPerEth(message.feeToken); - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory destChainDynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * destChainDynamicConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = - (configUSDCentToWei(destChainDynamicConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_ZeroDataAvailabilityMultiplier_Success() public { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigArgs = - new EVM2EVMMultiOnRamp.DestChainConfigArgs[](1); - EVM2EVMMultiOnRamp.DestChainConfig memory destChainConfig = s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR); - destChainConfigArgs[0] = EVM2EVMMultiOnRamp.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - dynamicConfig: destChainConfig.dynamicConfig - }); - destChainConfigArgs[0].dynamicConfig.destDataAvailabilityMultiplierBps = 0; - s_onRamp.applyDestChainConfigUpdates(destChainConfigArgs); - - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 premiumMultiplierWeiPerEth = s_onRamp.getPremiumMultiplierWeiPerEth(message.feeToken); - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory destChainDynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; - uint256 gasFeeUSD = (gasUsed * destChainDynamicConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = (configUSDCentToWei(destChainDynamicConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; - assertEq(totalPriceInFeeToken, feeAmount); - } - - function test_HighGasMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = MAX_GAS_LIMIT; - uint256 customDataSize = MAX_DATA_SIZE; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: new bytes(customDataSize), - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - - uint64 premiumMultiplierWeiPerEth = s_onRamp.getPremiumMultiplierWeiPerEth(message.feeToken); - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory destChainDynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + customDataSize * DEST_GAS_PER_PAYLOAD_BYTE; - uint256 gasFeeUSD = (gasUsed * destChainDynamicConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - uint256 messageFeeUSD = - (configUSDCentToWei(destChainDynamicConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_SingleTokenMessage_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 tokenAmount = 10000e18; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - message.feeToken = testTokens[i]; - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory destChainDynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - uint32 destBytesOverhead = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; - uint32 tokenBytesOverhead = - destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - - uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - - uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD - + s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; - uint256 gasFeeUSD = (gasUsed * destChainDynamicConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * s_onRamp.getPremiumMultiplierWeiPerEth(message.feeToken)); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, - USD_PER_DATA_AVAILABILITY_GAS, - message.data.length, - message.tokenAmounts.length, - tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, feeAmount); - } - } - - function test_MessageWithDataAndTokenTransfer_Success() public view { - address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; - uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; - - uint256 customGasLimit = 1_000_000; - for (uint256 i = 0; i < feeTokenPrices.length; ++i) { - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](2), - feeToken: testTokens[i], - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) - }); - uint64 premiumMultiplierWeiPerEth = s_onRamp.getPremiumMultiplierWeiPerEth(message.feeToken); - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory destChainDynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - - message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: 10000e18}); // feeTokenAmount - message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: 200000e18}); // customTokenAmount - message.data = "random bits and bytes that should be factored into the cost of the message"; - - uint32 tokenGasOverhead = 0; - uint32 tokenBytesOverhead = 0; - for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { - tokenGasOverhead += - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; - uint32 destBytesOverhead = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destBytesOverhead; - tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - } - - uint256 gasUsed = - customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; - uint256 gasFeeUSD = (gasUsed * destChainDynamicConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); - uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_onRamp.getDataAvailabilityCost( - DEST_CHAIN_SELECTOR, - USD_PER_DATA_AVAILABILITY_GAS, - message.data.length, - message.tokenAmounts.length, - tokenBytesOverhead - ); - - uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, s_onRamp.getFee(DEST_CHAIN_SELECTOR, message)); - } - } - - // Reverts - - function test_DestinationChainNotEnabled_Revert() public { - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1) - ); - s_onRamp.getFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); - } - - function test_NotAFeeToken_Revert() public { - address notAFeeToken = address(0x111111); - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); - message.feeToken = notAFeeToken; - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.NotAFeeToken.selector, notAFeeToken)); - - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } - - function test_MessageTooLarge_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.data = new bytes(MAX_DATA_SIZE + 1); - vm.expectRevert( - abi.encodeWithSelector(EVM2EVMMultiOnRamp.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length) - ); - - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } - - function test_TooManyTokens_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint256 tooMany = MAX_TOKENS_LENGTH + 1; - message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); - vm.expectRevert(EVM2EVMMultiOnRamp.UnsupportedNumberOfTokens.selector); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } - - // Asserts gasLimit must be <=maxGasLimit - function test_MessageGasLimitTooHigh_Revert() public { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.MessageGasLimitTooHigh.selector)); - s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - } -} - -contract EVM2EVMMultiOnRamp_getTokenTransferCost is EVM2EVMMultiOnRamp_getFeeSetup { - using USDPriceWith18Decimals for uint224; - - function test_NoTokenTransferChargesZeroFee_Success() public view { - Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(0, feeUSDWei); - assertEq(0, destGasOverhead); - assertEq(0, destBytesOverhead); - } - - function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); - - // Get config to assert it isn't set - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - assertFalse(transferFeeConfig.isEnabled); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // Assert that the default values are used - assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); - assertEq(DEFAULT_TOKEN_DEST_GAS_OVERHEAD, destGasOverhead); - assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); - } - - function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - assertEq(configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_FeeTokenBpsFee_Success() public view { - uint256 tokenAmount = 10000e18; - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); - uint256 bpsUSDWei = - applyBpsRatio(usdWei, s_tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_WETHTokenBpsFee_Success() public view { - uint256 tokenAmount = 100e18; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](1), - feeToken: s_sourceRouter.getWrappedNative(), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceRouter.getWrappedNative(), amount: tokenAmount}); - - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_wrappedTokenPrice, tokenAmount); - uint256 bpsUSDWei = - applyBpsRatio(usdWei, s_tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_CustomTokenBpsFee_Success() public view { - uint256 tokenAmount = 200000e18; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](1), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); - - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory transferFeeConfig = - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); - - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - uint256 usdWei = calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); - uint256 bpsUSDWei = - applyBpsRatio(usdWei, s_tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[2].tokenTransferFeeConfig.deciBps); - - assertEq(bpsUSDWei, feeUSDWei); - assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); - assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); - } - - function test_ZeroFeeConfigChargesMinFee_Success() public { - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = EVM2EVMMultiOnRamp - .TokenTransferFeeConfig({ - minFeeUSDCents: 1, - maxFeeUSDCents: 0, - deciBps: 0, - destGasOverhead: 0, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), - isEnabled: true - }); - s_onRamp.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](0) - ); - - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - - // if token charges 0 bps, it should cost minFee to transfer - assertEq( - configUSDCentToWei(tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.minFeeUSDCents), - feeUSDWei - ); - assertEq(0, destGasOverhead); - assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); - } - - function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { - // It shouldn't be possible to pay materially lower fees by splitting up the transfers. - // Note it is possible to pay higher fees since the minimum fees are added. - EVM2EVMMultiOnRamp.DestChainDynamicConfig memory dynamicConfig = - s_onRamp.getDestChainConfig(DEST_CHAIN_SELECTOR).dynamicConfig; - transfers = bound(transfers, 1, dynamicConfig.maxNumberOfTokensPerMsg); - // Cap amount to avoid overflow - amount = bound(amount, 0, 1e36); - Client.EVMTokenAmount[] memory multiple = new Client.EVMTokenAmount[](transfers); - for (uint256 i = 0; i < transfers; ++i) { - multiple[i] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount}); - } - Client.EVMTokenAmount[] memory single = new Client.EVMTokenAmount[](1); - single[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount * transfers}); - - address feeToken = s_sourceRouter.getWrappedNative(); - - (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); - (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); - - // Note that there can be a rounding error once per split. - assertGe(feeMultipleUSDWei, (feeSingleUSDWei - dynamicConfig.maxNumberOfTokensPerMsg)); - assertEq(gasOverheadMultiple, gasOverheadSingle * transfers); - assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); - } - - function test_MixedTokenTransferFee_Success() public view { - address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; - uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; - EVM2EVMMultiOnRamp.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), - s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) - ]; - - Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](3), - feeToken: s_sourceRouter.getWrappedNative(), - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - uint256 expectedTotalGas = 0; - uint256 expectedTotalBytes = 0; - - // Start with small token transfers, total bps fee is lower than min token transfer fee - for (uint256 i = 0; i < testTokens.length; ++i) { - message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); - expectedTotalGas += s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]).destGasOverhead; - expectedTotalBytes += s_onRamp.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]).destBytesOverhead; - } - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - - uint256 expectedFeeUSDWei = 0; - for (uint256 i = 0; i < testTokens.length; ++i) { - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[i].minFeeUSDCents); - } - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - - // Set 1st token transfer to a meaningful amount so its bps fee is now between min and max fee - message.tokenAmounts[0] = Client.EVMTokenAmount({token: testTokens[0], amount: 10000e18}); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - expectedFeeUSDWei = applyBpsRatio( - calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps - ); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].minFeeUSDCents); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - - // Set 2nd token transfer to a large amount that is higher than maxFeeUSD - message.tokenAmounts[1] = Client.EVMTokenAmount({token: testTokens[1], amount: 1e36}); - - (feeUSDWei, destGasOverhead, destBytesOverhead) = - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); - expectedFeeUSDWei = applyBpsRatio( - calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps - ); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].maxFeeUSDCents); - expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); - - assertEq(expectedFeeUSDWei, feeUSDWei); - assertEq(expectedTotalGas, destGasOverhead); - assertEq(expectedTotalBytes, destBytesOverhead); - } - - // reverts - - function test_UnsupportedToken_Revert() public { - address NOT_SUPPORTED_TOKEN = address(123); - Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(NOT_SUPPORTED_TOKEN, 200); - - vm.expectRevert(abi.encodeWithSelector(EVM2EVMMultiOnRamp.UnsupportedToken.selector, NOT_SUPPORTED_TOKEN)); - - s_onRamp.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); - } -} - -contract EVM2EVMMultiOnRamp_setDynamicConfig is EVM2EVMMultiOnRampSetup { - function test_SetDynamicConfig_Success() public { - EVM2EVMMultiOnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); - EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ - router: address(2134), - priceRegistry: address(23423), - messageValidator: makeAddr("messageValidator"), - feeAggregator: FEE_AGGREGATOR - }); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.ConfigSet(staticConfig, newConfig); - - s_onRamp.setDynamicConfig(newConfig); - - EVM2EVMMultiOnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - assertEq(newConfig.router, gotDynamicConfig.router); - assertEq(newConfig.priceRegistry, gotDynamicConfig.priceRegistry); - } - - // Reverts - - function test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() public { - EVM2EVMMultiOnRamp.DynamicConfig memory newConfig = EVM2EVMMultiOnRamp.DynamicConfig({ - router: address(2134), - priceRegistry: address(0), - feeAggregator: FEE_AGGREGATOR, - messageValidator: makeAddr("messageValidator") - }); - - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); - s_onRamp.setDynamicConfig(newConfig); + vm.expectRevert(EVM2EVMMultiOnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); } function test_SetConfigInvalidConfig_Revert() public { @@ -1747,267 +701,6 @@ contract EVM2EVMMultiOnRamp_withdrawFeeTokens is EVM2EVMMultiOnRampSetup { } } -contract EVM2EVMMultiOnRamp_applyPremiumMultiplierWeiPerEthUpdates is EVM2EVMMultiOnRampSetup { - function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg - ) public { - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[](1); - premiumMultiplierWeiPerEthArgs[0] = premiumMultiplierWeiPerEthArg; - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthUpdated( - premiumMultiplierWeiPerEthArg.token, premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth - ); - - s_onRamp.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth, - s_onRamp.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[](1); - premiumMultiplierWeiPerEthArgs[0] = s_premiumMultiplierWeiPerEthArgs[0]; - premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthUpdated( - vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth - ); - - s_onRamp.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - s_premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, s_onRamp.getPremiumMultiplierWeiPerEth(vm.addr(1)) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[](2); - premiumMultiplierWeiPerEthArgs[0] = s_premiumMultiplierWeiPerEthArgs[0]; - premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); - premiumMultiplierWeiPerEthArgs[1].token = vm.addr(2); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthUpdated( - vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth - ); - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthUpdated( - vm.addr(2), premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth - ); - - s_onRamp.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - - assertEq( - premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, s_onRamp.getPremiumMultiplierWeiPerEth(vm.addr(1)) - ); - assertEq( - premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, s_onRamp.getPremiumMultiplierWeiPerEth(vm.addr(2)) - ); - } - - function test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() public { - vm.recordLogs(); - s_onRamp.applyPremiumMultiplierWeiPerEthUpdates(new EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[](0)); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_OnlyCallableByOwnerOrAdmin_Revert() public { - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; - vm.startPrank(STRANGER); - - vm.expectRevert("Only callable by owner"); - - s_onRamp.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); - } -} - -contract EVM2EVMMultiOnRamp_applyTokenTransferFeeConfigUpdates is EVM2EVMMultiOnRampSetup { - function test_Fuzz_ApplyTokenTransferFeeConfig_Success( - EVM2EVMMultiOnRamp.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs - ) public { - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(2, 2); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; - - for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { - for (uint256 j = 0; j < tokenTransferFeeConfigs.length; ++j) { - tokenTransferFeeConfigs[j].destBytesOverhead = uint32( - bound(tokenTransferFeeConfigs[j].destBytesOverhead, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, type(uint32).max) - ); - address feeToken = s_sourceTokens[j]; - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].token = feeToken; - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].tokenTransferFeeConfig = tokenTransferFeeConfigs[j]; - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[i].destChainSelector, feeToken, tokenTransferFeeConfigs[j] - ); - } - } - - s_onRamp.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](0) - ); - - for (uint256 i = 0; i < tokenTransferFeeConfigs.length; ++i) { - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigs[i], - s_onRamp.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i].token - ) - ); - } - } - - function test_ApplyTokenTransferFeeConfig_Success() public { - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 2); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = EVM2EVMMultiOnRamp - .TokenTransferFeeConfig({ - minFeeUSDCents: 6, - maxFeeUSDCents: 7, - deciBps: 8, - destGasOverhead: 9, - destBytesOverhead: 312, - isEnabled: true - }); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token = address(11); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = EVM2EVMMultiOnRamp - .TokenTransferFeeConfig({ - minFeeUSDCents: 12, - maxFeeUSDCents: 13, - deciBps: 14, - destGasOverhead: 15, - destBytesOverhead: 394, - isEnabled: true - }); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig - ); - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.TokenTransferFeeConfigUpdated( - tokenTransferFeeConfigArgs[0].destChainSelector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig - ); - - EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = - new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](0); - s_onRamp.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); - - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory config0 = s_onRamp.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory config1 = s_onRamp.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token - ); - - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig, config0 - ); - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 - ); - - // Remove only the first token and validate only the first token is removed - tokensToRemove = new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](1); - tokensToRemove[0] = EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs({ - destChainSelector: tokenTransferFeeConfigArgs[0].destChainSelector, - token: tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - }); - - vm.expectEmit(); - emit EVM2EVMMultiOnRamp.TokenTransferFeeConfigDeleted( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - - s_onRamp.applyTokenTransferFeeConfigUpdates(new EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[](0), tokensToRemove); - - config0 = s_onRamp.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token - ); - config1 = s_onRamp.getTokenTransferFeeConfig( - tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token - ); - - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory emptyConfig; - - _assertTokenTransferFeeConfigEqual(emptyConfig, config0); - _assertTokenTransferFeeConfigEqual( - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 - ); - } - - function test_ApplyTokenTransferFeeZeroInput() public { - vm.recordLogs(); - s_onRamp.applyTokenTransferFeeConfigUpdates( - new EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[](0), - new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](0) - ); - - assertEq(vm.getRecordedLogs().length, 0); - } - - // Reverts - - function test_OnlyCallableByOwnerOrAdmin_Revert() public { - vm.startPrank(STRANGER); - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; - - vm.expectRevert("Only callable by owner"); - - s_onRamp.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](0) - ); - } - - function test_InvalidDestBytesOverhead_Revert() public { - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); - tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = EVM2EVMMultiOnRamp - .TokenTransferFeeConfig({ - minFeeUSDCents: 6, - maxFeeUSDCents: 7, - deciBps: 8, - destGasOverhead: 9, - destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1), - isEnabled: true - }); - - vm.expectRevert( - abi.encodeWithSelector( - EVM2EVMMultiOnRamp.InvalidDestBytesOverhead.selector, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destBytesOverhead - ) - ); - - s_onRamp.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new EVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[](0) - ); - } -} - contract EVM2EVMMultiOnRamp_getTokenPool is EVM2EVMMultiOnRampSetup { function test_GetTokenPool_Success() public view { assertEq( @@ -2025,94 +718,3 @@ contract EVM2EVMMultiOnRamp_getTokenPool is EVM2EVMMultiOnRampSetup { assertEq(address(0), nonExistentPool); } } - -contract EVM2EVMMultiOnRamp_validateDestFamilyAddress is EVM2EVMMultiOnRampSetup { - function test_ValidEVMAddress_Success() public view { - bytes memory encodedAddress = abi.encode(address(10000)); - s_onRamp.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); - } - - function test_ValidNonEVMAddress_Success() public view { - s_onRamp.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); - } - - // Reverts - - function test_InvalidEVMAddress_Revert() public { - bytes memory invalidAddress = abi.encode(type(uint208).max); - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_onRamp.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); - } -} - -contract EVM2EVMMultiOnRamp_convertParsedExtraArgs is EVM2EVMMultiOnRampSetup { - EVM2EVMMultiOnRamp.DestChainDynamicConfig private s_destChainDynamicConfig; - - function setUp() public virtual override { - super.setUp(); - s_destChainDynamicConfig = _generateDestChainConfigArgs()[0].dynamicConfig; - } - - function test_EVMExtraArgsV1_Success() public view { - Client.EVMExtraArgsV1 memory inputArgs = Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - Client.EVMExtraArgsV2 memory expectedOutputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); - - vm.assertEq( - s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig), abi.encode(expectedOutputArgs) - ); - } - - function test_EVMExtraArgsV2_Success() public view { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - - vm.assertEq(s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig), abi.encode(inputArgs)); - } - - function test_EVMExtraArgsDefault_Success() public view { - Client.EVMExtraArgsV2 memory expectedOutputArgs = - Client.EVMExtraArgsV2({gasLimit: s_destChainDynamicConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); - - vm.assertEq(s_onRamp.convertParsedExtraArgs("", s_destChainDynamicConfig), abi.encode(expectedOutputArgs)); - } - - function test_EmptyExtraArgs_Success() public { - s_destChainDynamicConfig.chainFamilySelector = bytes4(uint32(1)); - vm.assertEq(s_onRamp.convertParsedExtraArgs("", s_destChainDynamicConfig), ""); - } - - // Reverts - - function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - // Invalidate selector - inputExtraArgs[0] = bytes1(uint8(0)); - - vm.expectRevert(EVM2EVMMultiOnRamp.InvalidExtraArgsTag.selector); - s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig); - } - - function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - s_destChainDynamicConfig.enforceOutOfOrder = true; - - vm.expectRevert(EVM2EVMMultiOnRamp.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig); - } - - function test_EVMExtraArgsGasLimitTooHigh_Revert() public { - Client.EVMExtraArgsV2 memory inputArgs = - Client.EVMExtraArgsV2({gasLimit: s_destChainDynamicConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); - bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - - vm.expectRevert(EVM2EVMMultiOnRamp.MessageGasLimitTooHigh.selector); - s_onRamp.convertParsedExtraArgs(inputExtraArgs, s_destChainDynamicConfig); - } -} diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol index 24a47d1aca..f085185753 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMMultiOnRampSetup.t.sol @@ -16,14 +16,11 @@ import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.so import {TokenSetup} from "../TokenSetup.t.sol"; import {EVM2EVMMultiOnRampHelper} from "../helpers/EVM2EVMMultiOnRampHelper.sol"; import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; +import {PriceRegistryFeeSetup} from "../priceRegistry/PriceRegistry.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { - address internal constant CUSTOM_TOKEN = address(12345); - uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM - +contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistryFeeSetup { uint256 internal immutable i_tokenAmount0 = 9; uint256 internal immutable i_tokenAmount1 = 7; @@ -33,72 +30,10 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { MessageInterceptorHelper internal s_outboundMessageValidator; address[] internal s_offRamps; NonceManager internal s_outboundNonceManager; - address internal s_destTokenPool = makeAddr("destTokenPool"); - address internal s_destToken = makeAddr("destToken"); - - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[] internal s_premiumMultiplierWeiPerEthArgs; - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] internal s_tokenTransferFeeConfigArgs; - function setUp() public virtual override(TokenSetup, PriceRegistrySetup) { + function setUp() public virtual override(TokenSetup, PriceRegistryFeeSetup) { TokenSetup.setUp(); - PriceRegistrySetup.setUp(); - - s_priceRegistry.updatePrices(getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); - - s_premiumMultiplierWeiPerEthArgs.push( - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs({ - token: s_sourceFeeToken, - premiumMultiplierWeiPerEth: 5e17 // 0.5x - }) - ); - s_premiumMultiplierWeiPerEthArgs.push( - EVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs({ - token: s_sourceRouter.getWrappedNative(), - premiumMultiplierWeiPerEth: 2e18 // 2x - }) - ); - - s_tokenTransferFeeConfigArgs.push(); - s_tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - s_tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - EVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs({ - token: s_sourceFeeToken, - tokenTransferFeeConfig: EVM2EVMMultiOnRamp.TokenTransferFeeConfig({ - minFeeUSDCents: 1_00, // 1 USD - maxFeeUSDCents: 1000_00, // 1,000 USD - deciBps: 2_5, // 2.5 bps, or 0.025% - destGasOverhead: 40_000, - destBytesOverhead: 32, - isEnabled: true - }) - }) - ); - s_tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - EVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs({ - token: s_sourceRouter.getWrappedNative(), - tokenTransferFeeConfig: EVM2EVMMultiOnRamp.TokenTransferFeeConfig({ - minFeeUSDCents: 50, // 0.5 USD - maxFeeUSDCents: 500_00, // 500 USD - deciBps: 5_0, // 5 bps, or 0.05% - destGasOverhead: 10_000, - destBytesOverhead: 100, - isEnabled: true - }) - }) - ); - s_tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - EVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs({ - token: CUSTOM_TOKEN, - tokenTransferFeeConfig: EVM2EVMMultiOnRamp.TokenTransferFeeConfig({ - minFeeUSDCents: 2_00, // 1 USD - maxFeeUSDCents: 2000_00, // 1,000 USD - deciBps: 10_0, // 10 bps, or 0.1% - destGasOverhead: 1, - destBytesOverhead: 200, - isEnabled: true - }) - }) - ); + PriceRegistryFeeSetup.setUp(); s_outboundMessageValidator = new MessageInterceptorHelper(); s_outboundNonceManager = new NonceManager(new address[](0)); @@ -135,32 +70,6 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { }); } - function _generateSingleTokenMessage( - address token, - uint256 amount - ) public view returns (Client.EVM2AnyMessage memory) { - Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); - tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); - - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: tokenAmounts, - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - - function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { - return Client.EVM2AnyMessage({ - receiver: abi.encode(OWNER), - data: "", - tokenAmounts: new Client.EVMTokenAmount[](0), - feeToken: s_sourceFeeToken, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) - }); - } - function _messageToEvent( Client.EVM2AnyMessage memory message, uint64 seqNum, @@ -181,58 +90,6 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { ); } - function _messageToEvent( - Client.EVM2AnyMessage memory message, - uint64 sourceChainSelector, - uint64 destChainSelector, - uint64 seqNum, - uint64 nonce, - uint256 feeTokenAmount, - address originalSender, - bytes32 metadataHash, - TokenAdminRegistry tokenAdminRegistry - ) internal view returns (Internal.EVM2AnyRampMessage memory) { - Client.EVMExtraArgsV2 memory extraArgs = s_onRamp.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); - - Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ - header: Internal.RampMessageHeader({ - messageId: "", - sourceChainSelector: sourceChainSelector, - destChainSelector: destChainSelector, - sequenceNumber: seqNum, - nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce - }), - sender: originalSender, - data: message.data, - receiver: message.receiver, - extraArgs: abi.encode(extraArgs), - feeToken: message.feeToken, - feeTokenAmount: feeTokenAmount, - tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) - }); - - for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - messageEvent.tokenAmounts[i] = _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry); - } - - messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); - return messageEvent; - } - - function _getSourceTokenData( - Client.EVMTokenAmount memory tokenAmount, - TokenAdminRegistry tokenAdminRegistry - ) internal view returns (Internal.RampTokenAmount memory) { - address destToken = s_destTokenBySourceToken[tokenAmount.token]; - - return Internal.RampTokenAmount({ - sourcePoolAddress: abi.encode(tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool), - destTokenAddress: abi.encode(destToken), - extraData: "", - amount: tokenAmount.amount - }); - } - function _generateDynamicMultiOnRampConfig( address router, address priceRegistry @@ -254,46 +111,6 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { return result; } - function _generateDestChainConfigArgs() internal pure returns (EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory) { - EVM2EVMMultiOnRamp.DestChainConfigArgs[] memory destChainConfigs = new EVM2EVMMultiOnRamp.DestChainConfigArgs[](1); - destChainConfigs[0] = EVM2EVMMultiOnRamp.DestChainConfigArgs({ - destChainSelector: DEST_CHAIN_SELECTOR, - dynamicConfig: EVM2EVMMultiOnRamp.DestChainDynamicConfig({ - isEnabled: true, - maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, - destGasOverhead: DEST_GAS_OVERHEAD, - destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, - destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, - destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, - destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - maxDataBytes: MAX_DATA_SIZE, - maxPerMsgGasLimit: MAX_GAS_LIMIT, - defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, - defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, - defaultTxGasLimit: GAS_LIMIT, - gasMultiplierWeiPerEth: 5e17, - networkFeeUSDCents: 1_00, - enforceOutOfOrder: false, - chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM - }) - }); - return destChainConfigs; - } - - function _generateTokenTransferFeeConfigArgs( - uint256 destChainSelectorLength, - uint256 tokenLength - ) internal pure returns (EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory) { - EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - new EVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[](destChainSelectorLength); - for (uint256 i = 0; i < destChainSelectorLength; ++i) { - tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs = - new EVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); - } - return tokenTransferFeeConfigArgs; - } - function _deployOnRamp( uint64 sourceChainSelector, address sourceRouter, @@ -302,17 +119,12 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { ) internal returns (EVM2EVMMultiOnRampHelper, bytes32 metadataHash) { EVM2EVMMultiOnRampHelper onRamp = new EVM2EVMMultiOnRampHelper( EVM2EVMMultiOnRamp.StaticConfig({ - linkToken: s_sourceTokens[0], chainSelector: sourceChainSelector, - maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, rmnProxy: address(s_mockRMN), nonceManager: nonceManager, tokenAdminRegistry: tokenAdminRegistry }), - _generateDynamicMultiOnRampConfig(sourceRouter, address(s_priceRegistry)), - _generateDestChainConfigArgs(), - s_premiumMultiplierWeiPerEthArgs, - s_tokenTransferFeeConfigArgs + _generateDynamicMultiOnRampConfig(sourceRouter, address(s_priceRegistry)) ); address[] memory authorizedCallers = new address[](1); @@ -349,34 +161,11 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { } } - function _assertDestChainConfigsEqual( - EVM2EVMMultiOnRamp.DestChainConfig memory a, - EVM2EVMMultiOnRamp.DestChainConfig memory b - ) internal pure { - assertEq(a.dynamicConfig.isEnabled, b.dynamicConfig.isEnabled); - assertEq(a.dynamicConfig.maxNumberOfTokensPerMsg, b.dynamicConfig.maxNumberOfTokensPerMsg); - assertEq(a.dynamicConfig.maxDataBytes, b.dynamicConfig.maxDataBytes); - assertEq(a.dynamicConfig.maxPerMsgGasLimit, b.dynamicConfig.maxPerMsgGasLimit); - assertEq(a.dynamicConfig.destGasOverhead, b.dynamicConfig.destGasOverhead); - assertEq(a.dynamicConfig.destGasPerPayloadByte, b.dynamicConfig.destGasPerPayloadByte); - assertEq(a.dynamicConfig.destDataAvailabilityOverheadGas, b.dynamicConfig.destDataAvailabilityOverheadGas); - assertEq(a.dynamicConfig.destGasPerDataAvailabilityByte, b.dynamicConfig.destGasPerDataAvailabilityByte); - assertEq(a.dynamicConfig.destDataAvailabilityMultiplierBps, b.dynamicConfig.destDataAvailabilityMultiplierBps); - assertEq(a.dynamicConfig.defaultTokenFeeUSDCents, b.dynamicConfig.defaultTokenFeeUSDCents); - assertEq(a.dynamicConfig.defaultTokenDestGasOverhead, b.dynamicConfig.defaultTokenDestGasOverhead); - assertEq(a.dynamicConfig.defaultTokenDestBytesOverhead, b.dynamicConfig.defaultTokenDestBytesOverhead); - assertEq(a.dynamicConfig.defaultTxGasLimit, b.dynamicConfig.defaultTxGasLimit); - assertEq(a.sequenceNumber, b.sequenceNumber); - assertEq(a.metadataHash, b.metadataHash); - } - function _assertStaticConfigsEqual( EVM2EVMMultiOnRamp.StaticConfig memory a, EVM2EVMMultiOnRamp.StaticConfig memory b ) internal pure { - assertEq(a.linkToken, b.linkToken); assertEq(a.chainSelector, b.chainSelector); - assertEq(a.maxFeeJuelsPerMsg, b.maxFeeJuelsPerMsg); assertEq(a.rmnProxy, b.rmnProxy); assertEq(a.tokenAdminRegistry, b.tokenAdminRegistry); } @@ -388,16 +177,4 @@ contract EVM2EVMMultiOnRampSetup is TokenSetup, PriceRegistrySetup { assertEq(a.router, b.router); assertEq(a.priceRegistry, b.priceRegistry); } - - function _assertTokenTransferFeeConfigEqual( - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory a, - EVM2EVMMultiOnRamp.TokenTransferFeeConfig memory b - ) internal pure { - assertEq(a.minFeeUSDCents, b.minFeeUSDCents); - assertEq(a.maxFeeUSDCents, b.maxFeeUSDCents); - assertEq(a.deciBps, b.deciBps); - assertEq(a.destGasOverhead, b.destGasOverhead); - assertEq(a.destBytesOverhead, b.destBytesOverhead); - assertEq(a.isEnabled, b.isEnabled); - } } 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 0695e9d7a3..6659b1217f 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol @@ -18,9 +18,6 @@ import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract EVM2EVMOnRampSetup is TokenSetup, PriceRegistrySetup { - address internal constant CUSTOM_TOKEN = address(12345); - uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM - uint256 internal immutable i_tokenAmount0 = 9; uint256 internal immutable i_tokenAmount1 = 7; diff --git a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol b/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol index bc1a473f3c..c3c22ef290 100644 --- a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol +++ b/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol @@ -1,12 +1,28 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; +import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; + import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; import {PriceRegistry} from "../../PriceRegistry.sol"; -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; + +import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; +import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; +import {TokenPool} from "../../pools/TokenPool.sol"; +import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; + import {TokenSetup} from "../TokenSetup.t.sol"; +import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; +import {PriceRegistryHelper} from "../helpers/PriceRegistryHelper.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; + import {Vm} from "forge-std/Vm.sol"; import {console} from "forge-std/console.sol"; @@ -14,12 +30,15 @@ contract PriceRegistrySetup is TokenSetup { uint112 internal constant USD_PER_GAS = 1e6; // 0.001 gwei uint112 internal constant USD_PER_DATA_AVAILABILITY_GAS = 1e9; // 1 gwei + address internal constant CUSTOM_TOKEN = address(12345); + uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM + // Encode L1 gas price and L2 gas price into a packed price. // L1 gas price is left-shifted to the higher-order bits. uint224 internal constant PACKED_USD_PER_GAS = (uint224(USD_PER_DATA_AVAILABILITY_GAS) << Internal.GAS_PRICE_BITS) + USD_PER_GAS; - PriceRegistry internal s_priceRegistry; + PriceRegistryHelper internal s_priceRegistry; // Cheat to store the price updates in storage since struct arrays aren't supported. bytes internal s_encodedInitialPriceUpdates; address internal s_weth; @@ -29,6 +48,9 @@ contract PriceRegistrySetup is TokenSetup { address[] internal s_destFeeTokens; uint224[] internal s_destTokenPrices; + PriceRegistry.PremiumMultiplierWeiPerEthArgs[] internal s_priceRegistryPremiumMultiplierWeiPerEthArgs; + PriceRegistry.TokenTransferFeeConfigArgs[] internal s_priceRegistryTokenTransferFeeConfigArgs; + mapping(address token => address dataFeedAddress) internal s_dataFeedByToken; function setUp() public virtual override { @@ -82,13 +104,81 @@ contract PriceRegistrySetup is TokenSetup { s_encodedInitialPriceUpdates = abi.encode(priceUpdates); - address[] memory priceUpdaters = new address[](0); + address[] memory priceUpdaters = new address[](1); + priceUpdaters[0] = OWNER; address[] memory feeTokens = new address[](2); feeTokens[0] = s_sourceTokens[0]; feeTokens[1] = s_weth; PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](0); - s_priceRegistry = new PriceRegistry(priceUpdaters, feeTokens, uint32(TWELVE_HOURS), tokenPriceFeedUpdates); + s_priceRegistryPremiumMultiplierWeiPerEthArgs.push( + PriceRegistry.PremiumMultiplierWeiPerEthArgs({ + token: s_sourceFeeToken, + premiumMultiplierWeiPerEth: 5e17 // 0.5x + }) + ); + s_priceRegistryPremiumMultiplierWeiPerEthArgs.push( + PriceRegistry.PremiumMultiplierWeiPerEthArgs({ + token: s_sourceRouter.getWrappedNative(), + premiumMultiplierWeiPerEth: 2e18 // 2x + }) + ); + + s_priceRegistryTokenTransferFeeConfigArgs.push(); + s_priceRegistryTokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ + token: s_sourceFeeToken, + tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ + minFeeUSDCents: 1_00, // 1 USD + maxFeeUSDCents: 1000_00, // 1,000 USD + deciBps: 2_5, // 2.5 bps, or 0.025% + destGasOverhead: 40_000, + destBytesOverhead: 32, + isEnabled: true + }) + }) + ); + s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ + token: s_sourceRouter.getWrappedNative(), + tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ + minFeeUSDCents: 50, // 0.5 USD + maxFeeUSDCents: 500_00, // 500 USD + deciBps: 5_0, // 5 bps, or 0.05% + destGasOverhead: 10_000, + destBytesOverhead: 100, + isEnabled: true + }) + }) + ); + s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ + token: CUSTOM_TOKEN, + tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ + minFeeUSDCents: 2_00, // 1 USD + maxFeeUSDCents: 2000_00, // 1,000 USD + deciBps: 10_0, // 10 bps, or 0.1% + destGasOverhead: 1, + destBytesOverhead: 200, + isEnabled: true + }) + }) + ); + + s_priceRegistry = new PriceRegistryHelper( + PriceRegistry.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: uint32(TWELVE_HOURS) + }), + priceUpdaters, + feeTokens, + tokenPriceFeedUpdates, + s_priceRegistryTokenTransferFeeConfigArgs, + s_priceRegistryPremiumMultiplierWeiPerEthArgs, + _generatePriceRegistryDestChainConfigArgs() + ); s_priceRegistry.updatePrices(priceUpdates); } @@ -140,6 +230,50 @@ contract PriceRegistrySetup is TokenSetup { return s_sourceTokens[0]; } + function _generateTokenTransferFeeConfigArgs( + uint256 destChainSelectorLength, + uint256 tokenLength + ) internal pure returns (PriceRegistry.TokenTransferFeeConfigArgs[] memory) { + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + new PriceRegistry.TokenTransferFeeConfigArgs[](destChainSelectorLength); + for (uint256 i = 0; i < destChainSelectorLength; ++i) { + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs = + new PriceRegistry.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); + } + return tokenTransferFeeConfigArgs; + } + + function _generatePriceRegistryDestChainConfigArgs() + internal + pure + returns (PriceRegistry.DestChainConfigArgs[] memory) + { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigs = new PriceRegistry.DestChainConfigArgs[](1); + destChainConfigs[0] = PriceRegistry.DestChainConfigArgs({ + destChainSelector: DEST_CHAIN_SELECTOR, + destChainConfig: PriceRegistry.DestChainConfig({ + isEnabled: true, + maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, + destGasOverhead: DEST_GAS_OVERHEAD, + destGasPerPayloadByte: DEST_GAS_PER_PAYLOAD_BYTE, + destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, + destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, + destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, + maxDataBytes: MAX_DATA_SIZE, + maxPerMsgGasLimit: MAX_GAS_LIMIT, + defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, + defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, + defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, + defaultTxGasLimit: GAS_LIMIT, + gasMultiplierWeiPerEth: 5e17, + networkFeeUSDCents: 1_00, + enforceOutOfOrder: false, + chainFamilySelector: Internal.CHAIN_FAMILY_SELECTOR_EVM + }) + }); + return destChainConfigs; + } + function _assertTokenPriceFeedConfigEquality( IPriceRegistry.TokenPriceFeedConfig memory config1, IPriceRegistry.TokenPriceFeedConfig memory config2 @@ -157,6 +291,157 @@ contract PriceRegistrySetup is TokenSetup { config, IPriceRegistry.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) ); } + + function _assertTokenTransferFeeConfigEqual( + PriceRegistry.TokenTransferFeeConfig memory a, + PriceRegistry.TokenTransferFeeConfig memory b + ) internal pure { + assertEq(a.minFeeUSDCents, b.minFeeUSDCents); + assertEq(a.maxFeeUSDCents, b.maxFeeUSDCents); + assertEq(a.deciBps, b.deciBps); + assertEq(a.destGasOverhead, b.destGasOverhead); + assertEq(a.destBytesOverhead, b.destBytesOverhead); + assertEq(a.isEnabled, b.isEnabled); + } + + function _assertPriceRegistryStaticConfigsEqual( + PriceRegistry.StaticConfig memory a, + PriceRegistry.StaticConfig memory b + ) internal pure { + assertEq(a.linkToken, b.linkToken); + assertEq(a.maxFeeJuelsPerMsg, b.maxFeeJuelsPerMsg); + } + + function _assertPriceRegistryDestChainConfigsEqual( + PriceRegistry.DestChainConfig memory a, + PriceRegistry.DestChainConfig memory b + ) internal pure { + assertEq(a.isEnabled, b.isEnabled); + assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); + assertEq(a.maxDataBytes, b.maxDataBytes); + assertEq(a.maxPerMsgGasLimit, b.maxPerMsgGasLimit); + assertEq(a.destGasOverhead, b.destGasOverhead); + assertEq(a.destGasPerPayloadByte, b.destGasPerPayloadByte); + assertEq(a.destDataAvailabilityOverheadGas, b.destDataAvailabilityOverheadGas); + assertEq(a.destGasPerDataAvailabilityByte, b.destGasPerDataAvailabilityByte); + assertEq(a.destDataAvailabilityMultiplierBps, b.destDataAvailabilityMultiplierBps); + assertEq(a.defaultTokenFeeUSDCents, b.defaultTokenFeeUSDCents); + assertEq(a.defaultTokenDestGasOverhead, b.defaultTokenDestGasOverhead); + assertEq(a.defaultTokenDestBytesOverhead, b.defaultTokenDestBytesOverhead); + assertEq(a.defaultTxGasLimit, b.defaultTxGasLimit); + } +} + +contract PriceRegistryFeeSetup is PriceRegistrySetup { + uint224 internal s_feeTokenPrice; + uint224 internal s_wrappedTokenPrice; + uint224 internal s_customTokenPrice; + + address internal s_selfServeTokenDefaultPricing = makeAddr("self-serve-token-default-pricing"); + + address internal s_destTokenPool = makeAddr("destTokenPool"); + address internal s_destToken = makeAddr("destToken"); + + function setUp() public virtual override { + super.setUp(); + + s_feeTokenPrice = s_sourceTokenPrices[0]; + s_wrappedTokenPrice = s_sourceTokenPrices[2]; + s_customTokenPrice = CUSTOM_TOKEN_PRICE; + + s_priceRegistry.updatePrices(getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); + } + + function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](0), + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + function _generateSingleTokenMessage( + address token, + uint256 amount + ) public view returns (Client.EVM2AnyMessage memory) { + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1); + tokenAmounts[0] = Client.EVMTokenAmount({token: token, amount: amount}); + + return Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: tokenAmounts, + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + } + + function _messageToEvent( + Client.EVM2AnyMessage memory message, + uint64 sourceChainSelector, + uint64 destChainSelector, + uint64 seqNum, + uint64 nonce, + uint256 feeTokenAmount, + address originalSender, + bytes32 metadataHash, + TokenAdminRegistry tokenAdminRegistry + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + Client.EVMExtraArgsV2 memory extraArgs = + s_priceRegistry.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); + + Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ + header: Internal.RampMessageHeader({ + messageId: "", + sourceChainSelector: sourceChainSelector, + destChainSelector: destChainSelector, + sequenceNumber: seqNum, + nonce: extraArgs.allowOutOfOrderExecution ? 0 : nonce + }), + sender: originalSender, + data: message.data, + receiver: message.receiver, + extraArgs: Client._argsToBytes(extraArgs), + feeToken: message.feeToken, + feeTokenAmount: feeTokenAmount, + tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) + }); + + for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { + messageEvent.tokenAmounts[i] = _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry); + } + + messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); + return messageEvent; + } + + function _getSourceTokenData( + Client.EVMTokenAmount memory tokenAmount, + TokenAdminRegistry tokenAdminRegistry + ) internal view returns (Internal.RampTokenAmount memory) { + address destToken = s_destTokenBySourceToken[tokenAmount.token]; + + return Internal.RampTokenAmount({ + sourcePoolAddress: abi.encode(tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool), + destTokenAddress: abi.encode(destToken), + extraData: "", + amount: tokenAmount.amount + }); + } + + function calcUSDValueFromTokenAmount(uint224 tokenPrice, uint256 tokenAmount) internal pure returns (uint256) { + return (tokenPrice * tokenAmount) / 1e18; + } + + function applyBpsRatio(uint256 tokenAmount, uint16 ratio) internal pure returns (uint256) { + return (tokenAmount * ratio) / 1e5; + } + + function configUSDCentToWei(uint256 usdCent) internal pure returns (uint256) { + return usdCent * 1e16; + } } contract PriceRegistry_constructor is PriceRegistrySetup { @@ -173,10 +458,25 @@ contract PriceRegistry_constructor is PriceRegistrySetup { tokenPriceFeedUpdates[1] = getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[1], s_dataFeedByToken[s_sourceTokens[1]], 6); - s_priceRegistry = new PriceRegistry(priceUpdaters, feeTokens, uint32(TWELVE_HOURS), tokenPriceFeedUpdates); + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: uint32(TWELVE_HOURS) + }); + s_priceRegistry = new PriceRegistryHelper( + staticConfig, + priceUpdaters, + feeTokens, + tokenPriceFeedUpdates, + s_priceRegistryTokenTransferFeeConfigArgs, + s_priceRegistryPremiumMultiplierWeiPerEthArgs, + destChainConfigArgs + ); + + _assertPriceRegistryStaticConfigsEqual(s_priceRegistry.getStaticConfig(), staticConfig); assertEq(feeTokens, s_priceRegistry.getFeeTokens()); - assertEq(uint32(TWELVE_HOURS), s_priceRegistry.getStalenessThreshold()); assertEq(priceUpdaters, s_priceRegistry.getAllAuthorizedCallers()); assertEq(s_priceRegistry.typeAndVersion(), "PriceRegistry 1.6.0-dev"); @@ -187,12 +487,95 @@ contract PriceRegistry_constructor is PriceRegistrySetup { _assertTokenPriceFeedConfigEquality( tokenPriceFeedUpdates[1].feedConfig, s_priceRegistry.getTokenPriceFeedConfig(s_sourceTokens[1]) ); + + assertEq( + s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_priceRegistry.getPremiumMultiplierWeiPerEth(s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].token) + ); + + assertEq( + s_priceRegistryPremiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, + s_priceRegistry.getPremiumMultiplierWeiPerEth(s_priceRegistryPremiumMultiplierWeiPerEthArgs[1].token) + ); + + PriceRegistry.TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = + s_priceRegistryTokenTransferFeeConfigArgs[0]; + for (uint256 i = 0; i < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++i) { + PriceRegistry.TokenTransferFeeConfigSingleTokenArgs memory tokenFeeArgs = + s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i]; + + _assertTokenTransferFeeConfigEqual( + tokenFeeArgs.tokenTransferFeeConfig, + s_priceRegistry.getTokenTransferFeeConfig(tokenTransferFeeConfigArg.destChainSelector, tokenFeeArgs.token) + ); + } + + for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { + PriceRegistry.DestChainConfig memory expectedConfig = destChainConfigArgs[i].destChainConfig; + uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; + + _assertPriceRegistryDestChainConfigsEqual(expectedConfig, s_priceRegistry.getDestChainConfig(destChainSelector)); + } } function test_InvalidStalenessThreshold_Revert() public { - vm.expectRevert(PriceRegistry.InvalidStalenessThreshold.selector); - s_priceRegistry = - new PriceRegistry(new address[](0), new address[](0), 0, new PriceRegistry.TokenPriceFeedUpdate[](0)); + PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: 0 + }); + + vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); + + s_priceRegistry = new PriceRegistryHelper( + staticConfig, + new address[](0), + new address[](0), + new PriceRegistry.TokenPriceFeedUpdate[](0), + s_priceRegistryTokenTransferFeeConfigArgs, + s_priceRegistryPremiumMultiplierWeiPerEthArgs, + new PriceRegistry.DestChainConfigArgs[](0) + ); + } + + function test_InvalidLinkTokenEqZeroAddress_Revert() public { + PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + linkToken: address(0), + maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, + stalenessThreshold: uint32(TWELVE_HOURS) + }); + + vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); + + s_priceRegistry = new PriceRegistryHelper( + staticConfig, + new address[](0), + new address[](0), + new PriceRegistry.TokenPriceFeedUpdate[](0), + s_priceRegistryTokenTransferFeeConfigArgs, + s_priceRegistryPremiumMultiplierWeiPerEthArgs, + new PriceRegistry.DestChainConfigArgs[](0) + ); + } + + function test_InvalidMaxFeeJuelsPerMsg_Revert() public { + PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + linkToken: s_sourceTokens[0], + maxFeeJuelsPerMsg: 0, + stalenessThreshold: uint32(TWELVE_HOURS) + }); + + vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); + + s_priceRegistry = new PriceRegistryHelper( + staticConfig, + new address[](0), + new address[](0), + new PriceRegistry.TokenPriceFeedUpdate[](0), + s_priceRegistryTokenTransferFeeConfigArgs, + s_priceRegistryPremiumMultiplierWeiPerEthArgs, + new PriceRegistry.DestChainConfigArgs[](0) + ); } } @@ -559,7 +942,7 @@ contract PriceRegistry_updatePrices is PriceRegistrySetup { // Reverts - function test_OnlyCallableByUpdaterOrOwner_Revert() public { + function test_OnlyCallableByUpdater_Revert() public { Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: new Internal.GasPriceUpdate[](0) @@ -782,3 +1165,1378 @@ contract PriceRegistry_updateTokenPriceFeeds is PriceRegistrySetup { s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); } } + +contract PriceRegistry_applyDestChainConfigUpdates is PriceRegistrySetup { + function test_Fuzz_applyDestChainConfigUpdates_Success(PriceRegistry.DestChainConfigArgs memory destChainConfigArgs) + public + { + vm.assume(destChainConfigArgs.destChainSelector != 0); + vm.assume(destChainConfigArgs.destChainConfig.maxPerMsgGasLimit != 0); + destChainConfigArgs.destChainConfig.defaultTxGasLimit = uint32( + bound( + destChainConfigArgs.destChainConfig.defaultTxGasLimit, 1, destChainConfigArgs.destChainConfig.maxPerMsgGasLimit + ) + ); + destChainConfigArgs.destChainConfig.defaultTokenDestBytesOverhead = uint32( + bound( + destChainConfigArgs.destChainConfig.defaultTokenDestBytesOverhead, + Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, + type(uint32).max + ) + ); + destChainConfigArgs.destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + + bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; + + PriceRegistry.DestChainConfigArgs[] memory newDestChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); + newDestChainConfigArgs[0] = destChainConfigArgs; + + if (isNewChain) { + vm.expectEmit(); + emit PriceRegistry.DestChainAdded(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); + } else { + vm.expectEmit(); + emit PriceRegistry.DestChainConfigUpdated( + destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig + ); + } + + s_priceRegistry.applyDestChainConfigUpdates(newDestChainConfigArgs); + + _assertPriceRegistryDestChainConfigsEqual( + destChainConfigArgs.destChainConfig, s_priceRegistry.getDestChainConfig(destChainConfigArgs.destChainSelector) + ); + } + + function test_applyDestChainConfigUpdates_Success() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](2); + destChainConfigArgs[0] = _generatePriceRegistryDestChainConfigArgs()[0]; + destChainConfigArgs[0].destChainConfig.isEnabled = false; + destChainConfigArgs[1] = _generatePriceRegistryDestChainConfigArgs()[0]; + destChainConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; + + vm.expectEmit(); + emit PriceRegistry.DestChainConfigUpdated(DEST_CHAIN_SELECTOR, destChainConfigArgs[0].destChainConfig); + vm.expectEmit(); + emit PriceRegistry.DestChainAdded(DEST_CHAIN_SELECTOR + 1, destChainConfigArgs[1].destChainConfig); + + vm.recordLogs(); + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + + PriceRegistry.DestChainConfig memory gotDestChainConfig0 = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + PriceRegistry.DestChainConfig memory gotDestChainConfig1 = + s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + + assertEq(vm.getRecordedLogs().length, 2); + _assertPriceRegistryDestChainConfigsEqual(destChainConfigArgs[0].destChainConfig, gotDestChainConfig0); + _assertPriceRegistryDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); + } + + function test_applyDestChainConfigUpdatesZeroIntput_Success() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](0); + + vm.recordLogs(); + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainConfig.defaultTxGasLimit = 0; + vm.expectRevert( + abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + // Allow setting to the max value + destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit; + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + + // Revert when exceeding max value + destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit + 1; + vm.expectRevert( + abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainSelector = 0; + vm.expectRevert( + abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_InvalidDestBytesOverhead_Revert() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainConfig.defaultTokenDestBytesOverhead = uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1); + + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, DEST_CHAIN_SELECTOR)); + + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + } + + function test_InvalidChainFamilySelector_Revert() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + + destChainConfigArg.destChainConfig.chainFamilySelector = bytes4(uint32(1)); + + vm.expectRevert( + abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + ); + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + } +} + +contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { + function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { + uint256 dataAvailabilityCostUSD = + s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; + uint256 expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + + // Test that the cost is destnation chain specific + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + destChainConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR + 1; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = + destChainConfig.destDataAvailabilityOverheadGas * 2; + destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = + destChainConfig.destGasPerDataAvailabilityByte * 2; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = + destChainConfig.destDataAvailabilityMultiplierBps * 2; + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + + destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + uint256 dataAvailabilityCostUSD2 = + s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; + expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD2); + assertFalse(dataAvailabilityCostUSD == dataAvailabilityCostUSD2); + } + + function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { + uint256 dataAvailabilityCostUSD = + s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 dataAvailabilityLengthBytes = + Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + 100 + (5 * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; + uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + + destChainConfig.destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; + uint256 expectedDataAvailabilityCostUSD = + USD_PER_DATA_AVAILABILITY_GAS * dataAvailabilityGas * destChainConfig.destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + } + + function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { + uint256 dataAvailabilityCostUSD = + s_priceRegistry.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + + assertEq(dataAvailabilityCostUSD, 0); + } + + function test_Fuzz_ZeroDataAvailabilityGasPriceAlwaysCalculatesZeroDataAvailabilityCost_Success( + uint64 messageDataLength, + uint32 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) public view { + uint256 dataAvailabilityCostUSD = s_priceRegistry.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, 0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead + ); + + assertEq(0, dataAvailabilityCostUSD); + } + + function test_Fuzz_CalculateDataAvailabilityCost_Success( + uint64 destChainSelector, + uint32 destDataAvailabilityOverheadGas, + uint16 destGasPerDataAvailabilityByte, + uint16 destDataAvailabilityMultiplierBps, + uint112 dataAvailabilityGasPrice, + uint64 messageDataLength, + uint32 numberOfTokens, + uint32 tokenTransferBytesOverhead + ) public { + vm.assume(destChainSelector != 0); + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(destChainSelector); + destChainConfigArgs[0] = + PriceRegistry.DestChainConfigArgs({destChainSelector: destChainSelector, destChainConfig: destChainConfig}); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; + destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; + destChainConfigArgs[0].destChainConfig.defaultTxGasLimit = GAS_LIMIT; + destChainConfigArgs[0].destChainConfig.maxPerMsgGasLimit = GAS_LIMIT; + destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; + destChainConfigArgs[0].destChainConfig.defaultTokenDestBytesOverhead = DEFAULT_TOKEN_BYTES_OVERHEAD; + + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + + uint256 dataAvailabilityCostUSD = s_priceRegistry.getDataAvailabilityCost( + destChainConfigArgs[0].destChainSelector, + dataAvailabilityGasPrice, + messageDataLength, + numberOfTokens, + tokenTransferBytesOverhead + ); + + uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + messageDataLength + + (numberOfTokens * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + tokenTransferBytesOverhead; + + uint256 dataAvailabilityGas = + destDataAvailabilityOverheadGas + destGasPerDataAvailabilityByte * dataAvailabilityLengthBytes; + uint256 expectedDataAvailabilityCostUSD = + dataAvailabilityGasPrice * dataAvailabilityGas * destDataAvailabilityMultiplierBps * 1e14; + + assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); + } +} + +contract PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates is PriceRegistrySetup { + function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( + PriceRegistry.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg + ) public { + PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](1); + premiumMultiplierWeiPerEthArgs[0] = premiumMultiplierWeiPerEthArg; + + vm.expectEmit(); + emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + premiumMultiplierWeiPerEthArg.token, premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth + ); + + s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth, + s_priceRegistry.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { + PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](1); + premiumMultiplierWeiPerEthArgs[0] = s_priceRegistryPremiumMultiplierWeiPerEthArgs[0]; + premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); + + vm.expectEmit(); + emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth + ); + + s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(1)) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { + PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](2); + premiumMultiplierWeiPerEthArgs[0] = s_priceRegistryPremiumMultiplierWeiPerEthArgs[0]; + premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); + premiumMultiplierWeiPerEthArgs[1].token = vm.addr(2); + + vm.expectEmit(); + emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth + ); + vm.expectEmit(); + emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + vm.addr(2), premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth + ); + + s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + + assertEq( + premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(1)) + ); + assertEq( + premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, + s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(2)) + ); + } + + function test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() public { + vm.recordLogs(); + s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](0)); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_OnlyCallableByOwnerOrAdmin_Revert() public { + PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; + vm.startPrank(STRANGER); + + vm.expectRevert("Only callable by owner"); + + s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + } +} + +contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup { + function test_Fuzz_ApplyTokenTransferFeeConfig_Success( + PriceRegistry.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs + ) public { + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + _generateTokenTransferFeeConfigArgs(2, 2); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; + + for (uint256 i = 0; i < tokenTransferFeeConfigArgs.length; ++i) { + for (uint256 j = 0; j < tokenTransferFeeConfigs.length; ++j) { + tokenTransferFeeConfigs[j].destBytesOverhead = uint32( + bound(tokenTransferFeeConfigs[j].destBytesOverhead, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, type(uint32).max) + ); + address feeToken = s_sourceTokens[j]; + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].token = feeToken; + tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].tokenTransferFeeConfig = tokenTransferFeeConfigs[j]; + + vm.expectEmit(); + emit PriceRegistry.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[i].destChainSelector, feeToken, tokenTransferFeeConfigs[j] + ); + } + } + + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + ); + + for (uint256 i = 0; i < tokenTransferFeeConfigs.length; ++i) { + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigs[i], + s_priceRegistry.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i].token + ) + ); + } + } + + function test_ApplyTokenTransferFeeConfig_Success() public { + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + _generateTokenTransferFeeConfigArgs(1, 2); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry + .TokenTransferFeeConfig({ + minFeeUSDCents: 6, + maxFeeUSDCents: 7, + deciBps: 8, + destGasOverhead: 9, + destBytesOverhead: 312, + isEnabled: true + }); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token = address(11); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = PriceRegistry + .TokenTransferFeeConfig({ + minFeeUSDCents: 12, + maxFeeUSDCents: 13, + deciBps: 14, + destGasOverhead: 15, + destBytesOverhead: 394, + isEnabled: true + }); + + vm.expectEmit(); + emit PriceRegistry.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig + ); + vm.expectEmit(); + emit PriceRegistry.TokenTransferFeeConfigUpdated( + tokenTransferFeeConfigArgs[0].destChainSelector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig + ); + + PriceRegistry.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = + new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0); + s_priceRegistry.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); + + PriceRegistry.TokenTransferFeeConfig memory config0 = s_priceRegistry.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + PriceRegistry.TokenTransferFeeConfig memory config1 = s_priceRegistry.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token + ); + + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig, config0 + ); + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 + ); + + // Remove only the first token and validate only the first token is removed + tokensToRemove = new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](1); + tokensToRemove[0] = PriceRegistry.TokenTransferFeeConfigRemoveArgs({ + destChainSelector: tokenTransferFeeConfigArgs[0].destChainSelector, + token: tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + }); + + vm.expectEmit(); + emit PriceRegistry.TokenTransferFeeConfigDeleted( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + new PriceRegistry.TokenTransferFeeConfigArgs[](0), tokensToRemove + ); + + config0 = s_priceRegistry.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token + ); + config1 = s_priceRegistry.getTokenTransferFeeConfig( + tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token + ); + + PriceRegistry.TokenTransferFeeConfig memory emptyConfig; + + _assertTokenTransferFeeConfigEqual(emptyConfig, config0); + _assertTokenTransferFeeConfigEqual( + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig, config1 + ); + } + + function test_ApplyTokenTransferFeeZeroInput() public { + vm.recordLogs(); + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + new PriceRegistry.TokenTransferFeeConfigArgs[](0), new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + ); + + assertEq(vm.getRecordedLogs().length, 0); + } + + // Reverts + + function test_OnlyCallableByOwnerOrAdmin_Revert() public { + vm.startPrank(STRANGER); + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; + + vm.expectRevert("Only callable by owner"); + + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + ); + } + + function test_InvalidDestBytesOverhead_Revert() public { + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry + .TokenTransferFeeConfig({ + minFeeUSDCents: 6, + maxFeeUSDCents: 7, + deciBps: 8, + destGasOverhead: 9, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1), + isEnabled: true + }); + + vm.expectRevert( + abi.encodeWithSelector( + PriceRegistry.InvalidDestBytesOverhead.selector, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destBytesOverhead + ) + ); + + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + ); + } +} + +contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { + using USDPriceWith18Decimals for uint224; + + function test_NoTokenTransferChargesZeroFee_Success() public view { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(0, feeUSDWei); + assertEq(0, destGasOverhead); + assertEq(0, destBytesOverhead); + } + + function test_getTokenTransferCost_selfServeUsesDefaults_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); + + // Get config to assert it isn't set + PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + assertFalse(transferFeeConfig.isEnabled); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + // Assert that the default values are used + assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); + assertEq(DEFAULT_TOKEN_DEST_GAS_OVERHEAD, destGasOverhead); + assertEq(DEFAULT_TOKEN_BYTES_OVERHEAD, destBytesOverhead); + } + + function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); + PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); + PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); + PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + assertEq(configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_FeeTokenBpsFee_Success() public view { + uint256 tokenAmount = 10000e18; + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + uint256 usdWei = calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); + uint256 bpsUSDWei = applyBpsRatio( + usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps + ); + + assertEq(bpsUSDWei, feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_WETHTokenBpsFee_Success() public view { + uint256 tokenAmount = 100e18; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](1), + feeToken: s_sourceRouter.getWrappedNative(), + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceRouter.getWrappedNative(), amount: tokenAmount}); + + PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = s_priceRegistry.getTokenTransferCost( + DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts + ); + + uint256 usdWei = calcUSDValueFromTokenAmount(s_wrappedTokenPrice, tokenAmount); + uint256 bpsUSDWei = applyBpsRatio( + usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps + ); + + assertEq(bpsUSDWei, feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_CustomTokenBpsFee_Success() public view { + uint256 tokenAmount = 200000e18; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](1), + feeToken: s_sourceFeeToken, + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); + + PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + uint256 usdWei = calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); + uint256 bpsUSDWei = applyBpsRatio( + usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[2].tokenTransferFeeConfig.deciBps + ); + + assertEq(bpsUSDWei, feeUSDWei); + assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); + assertEq(transferFeeConfig.destBytesOverhead, destBytesOverhead); + } + + function test_ZeroFeeConfigChargesMinFee_Success() public { + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry + .TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), + isEnabled: true + }); + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + ); + + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + + // if token charges 0 bps, it should cost minFee to transfer + assertEq( + configUSDCentToWei(tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.minFeeUSDCents), + feeUSDWei + ); + assertEq(0, destGasOverhead); + assertEq(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, destBytesOverhead); + } + + function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { + // It shouldn't be possible to pay materially lower fees by splitting up the transfers. + // Note it is possible to pay higher fees since the minimum fees are added. + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + transfers = bound(transfers, 1, destChainConfig.maxNumberOfTokensPerMsg); + // Cap amount to avoid overflow + amount = bound(amount, 0, 1e36); + Client.EVMTokenAmount[] memory multiple = new Client.EVMTokenAmount[](transfers); + for (uint256 i = 0; i < transfers; ++i) { + multiple[i] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount}); + } + Client.EVMTokenAmount[] memory single = new Client.EVMTokenAmount[](1); + single[0] = Client.EVMTokenAmount({token: s_sourceTokens[0], amount: amount * transfers}); + + address feeToken = s_sourceRouter.getWrappedNative(); + + (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); + (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = + s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); + + // Note that there can be a rounding error once per split. + assertGe(feeMultipleUSDWei, (feeSingleUSDWei - destChainConfig.maxNumberOfTokensPerMsg)); + assertEq(gasOverheadMultiple, gasOverheadSingle * transfers); + assertEq(bytesOverheadMultiple, bytesOverheadSingle * transfers); + } + + function test_MixedTokenTransferFee_Success() public view { + address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; + uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; + PriceRegistry.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) + ]; + + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](3), + feeToken: s_sourceRouter.getWrappedNative(), + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT})) + }); + uint256 expectedTotalGas = 0; + uint256 expectedTotalBytes = 0; + + // Start with small token transfers, total bps fee is lower than min token transfer fee + for (uint256 i = 0; i < testTokens.length; ++i) { + message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); + expectedTotalGas += s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]).destGasOverhead; + expectedTotalBytes += + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]).destBytesOverhead; + } + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = s_priceRegistry.getTokenTransferCost( + DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts + ); + + uint256 expectedFeeUSDWei = 0; + for (uint256 i = 0; i < testTokens.length; ++i) { + expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[i].minFeeUSDCents); + } + + assertEq(expectedFeeUSDWei, feeUSDWei); + assertEq(expectedTotalGas, destGasOverhead); + assertEq(expectedTotalBytes, destBytesOverhead); + + // Set 1st token transfer to a meaningful amount so its bps fee is now between min and max fee + message.tokenAmounts[0] = Client.EVMTokenAmount({token: testTokens[0], amount: 10000e18}); + + (feeUSDWei, destGasOverhead, destBytesOverhead) = s_priceRegistry.getTokenTransferCost( + DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts + ); + expectedFeeUSDWei = applyBpsRatio( + calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps + ); + expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].minFeeUSDCents); + expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); + + assertEq(expectedFeeUSDWei, feeUSDWei); + assertEq(expectedTotalGas, destGasOverhead); + assertEq(expectedTotalBytes, destBytesOverhead); + + // Set 2nd token transfer to a large amount that is higher than maxFeeUSD + message.tokenAmounts[1] = Client.EVMTokenAmount({token: testTokens[1], amount: 1e36}); + + (feeUSDWei, destGasOverhead, destBytesOverhead) = s_priceRegistry.getTokenTransferCost( + DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts + ); + expectedFeeUSDWei = applyBpsRatio( + calcUSDValueFromTokenAmount(tokenPrices[0], message.tokenAmounts[0].amount), tokenTransferFeeConfigs[0].deciBps + ); + expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[1].maxFeeUSDCents); + expectedFeeUSDWei += configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); + + assertEq(expectedFeeUSDWei, feeUSDWei); + assertEq(expectedTotalGas, destGasOverhead); + assertEq(expectedTotalBytes, destBytesOverhead); + } +} + +contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { + using USDPriceWith18Decimals for uint224; + + function test_EmptyMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = testTokens[i]; + uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + uint256 messageFeeUSD = (configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_ZeroDataAvailabilityMultiplier_Success() public { + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + destChainConfigArgs[0] = + PriceRegistry.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: destChainConfig}); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); + + uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + uint256 messageFeeUSD = (configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD) / s_feeTokenPrice; + assertEq(totalPriceInFeeToken, feeAmount); + } + + function test_HighGasMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 customGasLimit = MAX_GAS_LIMIT; + uint256 customDataSize = MAX_DATA_SIZE; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: new bytes(customDataSize), + tokenAmounts: new Client.EVMTokenAmount[](0), + feeToken: testTokens[i], + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) + }); + + uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + + uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + customDataSize * DEST_GAS_PER_PAYLOAD_BYTE; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + uint256 messageFeeUSD = (configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); + uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_SingleTokenMessage_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 tokenAmount = 10000e18; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); + message.feeToken = testTokens[i]; + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + uint32 destBytesOverhead = + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; + uint32 tokenBytesOverhead = + destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; + + uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + + uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD + + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + (uint256 transferFeeUSD,,) = s_priceRegistry.getTokenTransferCost( + DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts + ); + uint256 messageFeeUSD = (transferFeeUSD * s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken)); + uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, + USD_PER_DATA_AVAILABILITY_GAS, + message.data.length, + message.tokenAmounts.length, + tokenBytesOverhead + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, feeAmount); + } + } + + function test_MessageWithDataAndTokenTransfer_Success() public view { + address[2] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative()]; + uint224[2] memory feeTokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice]; + + uint256 customGasLimit = 1_000_000; + for (uint256 i = 0; i < feeTokenPrices.length; ++i) { + Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ + receiver: abi.encode(OWNER), + data: "", + tokenAmounts: new Client.EVMTokenAmount[](2), + feeToken: testTokens[i], + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) + }); + uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); + PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + + message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: 10000e18}); // feeTokenAmount + message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: 200000e18}); // customTokenAmount + message.data = "random bits and bytes that should be factored into the cost of the message"; + + uint32 tokenGasOverhead = 0; + uint32 tokenBytesOverhead = 0; + for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { + tokenGasOverhead += + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; + uint32 destBytesOverhead = s_priceRegistry.getTokenTransferFeeConfig( + DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token + ).destBytesOverhead; + tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; + } + + uint256 gasUsed = + customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; + uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); + (uint256 transferFeeUSD,,) = s_priceRegistry.getTokenTransferCost( + DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts + ); + uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); + uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + DEST_CHAIN_SELECTOR, + USD_PER_DATA_AVAILABILITY_GAS, + message.data.length, + message.tokenAmounts.length, + tokenBytesOverhead + ); + + uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; + assertEq(totalPriceInFeeToken, s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message)); + } + } + + function test_Fuzz_EnforceOutOfOrder(bool enforce, bool allowOutOfOrderExecution) public { + // Update config to enforce allowOutOfOrderExecution = defaultVal. + vm.stopPrank(); + vm.startPrank(OWNER); + + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = enforce; + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = abi.encodeWithSelector( + Client.EVM_EXTRA_ARGS_V2_TAG, + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT * 2, allowOutOfOrderExecution: allowOutOfOrderExecution}) + ); + + // If enforcement is on, only true should be allowed. + if (enforce && !allowOutOfOrderExecution) { + vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + } + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + // Reverts + + function test_DestinationChainNotEnabled_Revert() public { + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); + } + + function test_EnforceOutOfOrder_Revert() public { + // Update config to enforce allowOutOfOrderExecution = true. + vm.stopPrank(); + vm.startPrank(OWNER); + + PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; + s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + vm.stopPrank(); + + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + // Empty extraArgs to should revert since it enforceOutOfOrder is true. + message.extraArgs = ""; + + vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_MessageTooLarge_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.data = new bytes(MAX_DATA_SIZE + 1); + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); + + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_TooManyTokens_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + uint256 tooMany = MAX_TOKENS_LENGTH + 1; + message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); + vm.expectRevert(PriceRegistry.UnsupportedNumberOfTokens.selector); + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + // Asserts gasLimit must be <=maxGasLimit + function test_MessageGasLimitTooHigh_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.MessageGasLimitTooHigh.selector)); + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_NotAFeeToken_Revert() public { + address notAFeeToken = address(0x111111); + Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); + message.feeToken = notAFeeToken; + + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, notAFeeToken)); + + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } + + function test_InvalidEVMAddress_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.receiver = abi.encode(type(uint208).max); + + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); + + s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + } +} + +contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { + using USDPriceWith18Decimals for uint224; + + function setUp() public virtual override { + super.setUp(); + } + + function test_WithLinkTokenAmount_Success() public view { + ( + uint256 msgFeeJuels, + /* bool isOutOfOrderExecution */ + , + /* bytes memory convertedExtraArgs */ + ) = s_priceRegistry.processMessageArgs( + DEST_CHAIN_SELECTOR, + // LINK + s_sourceTokens[0], + MAX_MSG_FEES_JUELS, + "" + ); + + assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); + } + + function test_WithConvertedTokenAmount_Success() public view { + address feeToken = s_sourceTokens[1]; + uint256 feeTokenAmount = 10_000 gwei; + uint256 expectedConvertedAmount = s_priceRegistry.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); + + ( + uint256 msgFeeJuels, + /* bool isOutOfOrderExecution */ + , + /* bytes memory convertedExtraArgs */ + ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, feeToken, feeTokenAmount, ""); + + assertEq(msgFeeJuels, expectedConvertedAmount); + } + + function test_WithEmptyEVMExtraArgs_Success() public view { + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs + ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, ""); + + assertEq(isOutOfOrderExecution, false); + assertEq( + convertedExtraArgs, Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR)) + ); + } + + function test_WithEVMExtraArgsV1_Success() public view { + bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); + + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs + ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); + + assertEq(isOutOfOrderExecution, false); + assertEq( + convertedExtraArgs, + Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + ); + } + + function test_WitEVMExtraArgsV2_Success() public view { + bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); + + ( + /* uint256 msgFeeJuels */ + , + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs + ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); + + assertEq(isOutOfOrderExecution, true); + assertEq( + convertedExtraArgs, + Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + ); + } + + // Reverts + + function test_MessageFeeTooHigh_Revert() public { + vm.expectRevert( + abi.encodeWithSelector(PriceRegistry.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + ); + + s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS + 1, ""); + } + + function test_InvalidExtraArgs_Revert() public { + vm.expectRevert(PriceRegistry.InvalidExtraArgsTag.selector); + + s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, "abcde"); + } + + function test_MalformedEVMExtraArgs_Revert() public { + // abi.decode error + vm.expectRevert(); + + s_priceRegistry.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})) + ); + } +} + +contract PriceRegistry_validatePoolReturnData is PriceRegistryFeeSetup { + function test_WithSingleToken_Success() public view { + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + + Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + + // No revert - successful + s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + } + + function test_TokenAmountArraysMismatching_Revert() public { + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + + Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + + // Revert due to index out of bounds access + vm.expectRevert(); + + s_priceRegistry.validatePoolReturnData( + DEST_CHAIN_SELECTOR, new Internal.RampTokenAmount[](1), new Client.EVMTokenAmount[](0) + ); + } + + function test_SourceTokenDataTooLarge_Revert() public { + address sourceETH = s_sourceTokens[1]; + + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1000; + sourceTokenAmounts[0].token = sourceETH; + + Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + + // No data set, should succeed + s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + + // Set max data length, should succeed + rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); + s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + + // Set data to max length +1, should revert + rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); + s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + + // Set token config to allow larger data + PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + _generateTokenTransferFeeConfigArgs(1, 1); + tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry + .TokenTransferFeeConfig({ + minFeeUSDCents: 1, + maxFeeUSDCents: 0, + deciBps: 0, + destGasOverhead: 0, + destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, + isEnabled: true + }); + s_priceRegistry.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + ); + + s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + + // Set the token data larger than the configured token data, should revert + rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); + + vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); + s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + } + + function test_InvalidEVMAddressDestToken_Revert() public { + bytes memory nonEvmAddress = abi.encode(type(uint208).max); + + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + sourceTokenAmounts[0].amount = 1e18; + sourceTokenAmounts[0].token = s_sourceTokens[0]; + + Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + rampTokenAmounts[0].destTokenAddress = nonEvmAddress; + + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); + s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + } +} + +contract PriceRegistry_validateDestFamilyAddress is PriceRegistrySetup { + function test_ValidEVMAddress_Success() public view { + bytes memory encodedAddress = abi.encode(address(10000)); + s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); + } + + function test_ValidNonEVMAddress_Success() public view { + s_priceRegistry.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); + } + + // Reverts + + function test_InvalidEVMAddress_Revert() public { + bytes memory invalidAddress = abi.encode(type(uint208).max); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); + s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + } + + function test_InvalidEVMAddressEncodePacked_Revert() public { + bytes memory invalidAddress = abi.encodePacked(address(234)); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); + s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + } + + function test_InvalidEVMAddressPrecompiles_Revert() public { + for (uint160 i = 0; i < Internal.PRECOMPILE_SPACE; ++i) { + bytes memory invalidAddress = abi.encode(address(i)); + vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); + s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + } + + s_priceRegistry.validateDestFamilyAddress( + Internal.CHAIN_FAMILY_SELECTOR_EVM, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))) + ); + } +} + +contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { + PriceRegistry.DestChainConfig private s_destChainConfig; + + function setUp() public virtual override { + super.setUp(); + s_destChainConfig = _generatePriceRegistryDestChainConfigArgs()[0].destChainConfig; + } + + function test_EVMExtraArgsV1_Success() public view { + Client.EVMExtraArgsV1 memory inputArgs = Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + Client.EVMExtraArgsV2 memory expectedOutputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); + + vm.assertEq( + abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), + abi.encode(expectedOutputArgs) + ); + } + + function test_EVMExtraArgsV2_Success() public view { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + + vm.assertEq( + abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(inputArgs) + ); + } + + function test_EVMExtraArgsDefault_Success() public view { + Client.EVMExtraArgsV2 memory expectedOutputArgs = + Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); + + vm.assertEq( + abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes("", s_destChainConfig)), abi.encode(expectedOutputArgs) + ); + } + + // Reverts + + function test_EVMExtraArgsInvalidExtraArgsTag_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + // Invalidate selector + inputExtraArgs[0] = bytes1(uint8(0)); + + vm.expectRevert(PriceRegistry.InvalidExtraArgsTag.selector); + s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + s_destChainConfig.enforceOutOfOrder = true; + + vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } + + function test_EVMExtraArgsGasLimitTooHigh_Revert() public { + Client.EVMExtraArgsV2 memory inputArgs = + Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); + bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); + + vm.expectRevert(PriceRegistry.MessageGasLimitTooHigh.selector); + s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + } +} diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go index e3dbca8359..e8c07cb93d 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp/evm_2_evm_multi_onramp.go @@ -43,37 +43,6 @@ type ClientEVMTokenAmount struct { Amount *big.Int } -type EVM2EVMMultiOnRampDestChainConfig struct { - DynamicConfig EVM2EVMMultiOnRampDestChainDynamicConfig - SequenceNumber uint64 - MetadataHash [32]byte -} - -type EVM2EVMMultiOnRampDestChainConfigArgs struct { - DestChainSelector uint64 - DynamicConfig EVM2EVMMultiOnRampDestChainDynamicConfig -} - -type EVM2EVMMultiOnRampDestChainDynamicConfig struct { - IsEnabled bool - MaxNumberOfTokensPerMsg uint16 - MaxDataBytes uint32 - MaxPerMsgGasLimit uint32 - DestGasOverhead uint32 - DestGasPerPayloadByte uint16 - DestDataAvailabilityOverheadGas uint32 - DestGasPerDataAvailabilityByte uint16 - DestDataAvailabilityMultiplierBps uint16 - DefaultTokenFeeUSDCents uint16 - DefaultTokenDestGasOverhead uint32 - DefaultTokenDestBytesOverhead uint32 - DefaultTxGasLimit uint64 - GasMultiplierWeiPerEth uint64 - NetworkFeeUSDCents uint32 - EnforceOutOfOrder bool - ChainFamilySelector [4]byte -} - type EVM2EVMMultiOnRampDynamicConfig struct { Router common.Address PriceRegistry common.Address @@ -81,44 +50,13 @@ type EVM2EVMMultiOnRampDynamicConfig struct { FeeAggregator common.Address } -type EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthArgs struct { - Token common.Address - PremiumMultiplierWeiPerEth uint64 -} - type EVM2EVMMultiOnRampStaticConfig struct { - LinkToken common.Address ChainSelector uint64 - MaxFeeJuelsPerMsg *big.Int RmnProxy common.Address NonceManager common.Address TokenAdminRegistry common.Address } -type EVM2EVMMultiOnRampTokenTransferFeeConfig struct { - MinFeeUSDCents uint32 - MaxFeeUSDCents uint32 - DeciBps uint16 - DestGasOverhead uint32 - DestBytesOverhead uint32 - IsEnabled bool -} - -type EVM2EVMMultiOnRampTokenTransferFeeConfigArgs struct { - DestChainSelector uint64 - TokenTransferFeeConfigs []EVM2EVMMultiOnRampTokenTransferFeeConfigSingleTokenArgs -} - -type EVM2EVMMultiOnRampTokenTransferFeeConfigRemoveArgs struct { - DestChainSelector uint64 - Token common.Address -} - -type EVM2EVMMultiOnRampTokenTransferFeeConfigSingleTokenArgs struct { - Token common.Address - TokenTransferFeeConfig EVM2EVMMultiOnRampTokenTransferFeeConfig -} - type InternalEVM2AnyRampMessage struct { Header InternalRampMessageHeader Sender common.Address @@ -146,15 +84,15 @@ type InternalRampTokenAmount struct { } var EVM2EVMMultiOnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"NotAFeeToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainDynamicConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"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\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainDynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"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\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101406040523480156200001257600080fd5b50604051620072053803806200720583398101604081905262000035916200146f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000214565b505085516001600160a01b031615905080620000e6575060208501516001600160401b0316155b80620000fd575060608501516001600160a01b0316155b8062000114575060808501516001600160a01b0316155b806200012b575060a08501516001600160a01b0316155b156200014a576040516306b7c75960e31b815260040160405180910390fd5b84516001600160a01b0390811660a090815260208701516001600160401b031660c05260408701516001600160601b031660809081526060880151831660e0528701518216610100528601511661012052620001a684620002bf565b620001b18362000482565b620001bc82620009c9565b60408051600080825260208201909252620002099183919062000202565b6040805180820190915260008082526020820152815260200190600190039081620001da5790505b5062000a95565b5050505050620018be565b336001600160a01b038216036200026e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b03161580620002e5575060608101516001600160a01b0316155b1562000304576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b039283166001600160a01b0319918216179091556020808401516003805491851691841691909117905560408085015160048054918616918516919091179055606080860151600580549187169190951617909355805160c0808201835260a080518716835290516001600160401b031693820193909352608080516001600160601b03168284015260e05186169482019490945261010051851693810193909352610120519093169082015290517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916200047791849082516001600160a01b0390811682526020808501516001600160401b0316818401526040808601516001600160601b03168185015260608087015184168186015260808088015185169086015260a0968701518416968501969096528451831660c085015290840151821660e084015283015181166101008301529190920151166101208201526101400190565b60405180910390a150565b60005b8151811015620009c5576000828281518110620004a657620004a6620015b5565b602002602001015190506000838381518110620004c757620004c7620015b5565b6020026020010151600001519050806001600160401b031660001480620004fe5750602082015161018001516001600160401b0316155b80620005245750602082015161020001516001600160e01b031916630a04b54b60e21b14155b156200054f5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b600060066000836001600160401b03166001600160401b03168152602001908152602001600020905060006040518060600160405280856020015181526020018360020160009054906101000a90046001600160401b03166001600160401b031681526020018360030154815250905080600001518260000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505081600301546000801b03620009205760c051604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f732160208201526001600160401b0392831691810191909152908416606082015230608082015260a00160408051601f1981840301815291815281516020909201919091208282018190526003840155516001600160401b038416907f26f8c55bd3f591fd6042c98ad4d707257cd565dc47609bfa3ba517400d0570449062000912908590620015cb565b60405180910390a2620009b5565b60208460200151610160015163ffffffff1610156200096d57602084015161016001516040516312766e0160e11b81526000600482015263ffffffff909116602482015260440162000083565b826001600160401b03167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb8560200151604051620009ac919062001767565b60405180910390a25b5050505080600101905062000485565b5050565b60005b8151811015620009c5576000828281518110620009ed57620009ed620015b5565b6020026020010151600001519050600083838151811062000a125762000a12620015b5565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101620009cc565b60005b825181101562000d0257600083828151811062000ab95762000ab9620015b5565b6020026020010151905060008160000151905060005b82602001515181101562000cf35760008360200151828151811062000af85762000af8620015b5565b602002602001015160200151905060008460200151838151811062000b215762000b21620015b5565b60200260200101516000015190506020826080015163ffffffff16101562000b7a5760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000ce0908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000acf565b50505080600101905062000a98565b5060005b815181101562000dc857600082828151811062000d275762000d27620015b5565b6020026020010151600001519050600083838151811062000d4c5762000d4c620015b5565b6020908102919091018101518101516001600160401b03841660008181526008845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d06565b505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171562000e085762000e0862000dcd565b60405290565b60405161022081016001600160401b038111828210171562000e085762000e0862000dcd565b60405160c081016001600160401b038111828210171562000e085762000e0862000dcd565b604051601f8201601f191681016001600160401b038111828210171562000e845762000e8462000dcd565b604052919050565b80516001600160a01b038116811462000ea457600080fd5b919050565b80516001600160401b038116811462000ea457600080fd5b60006080828403121562000ed457600080fd5b604051608081016001600160401b038111828210171562000ef95762000ef962000dcd565b60405290508062000f0a8362000e8c565b815262000f1a6020840162000e8c565b602082015262000f2d6040840162000e8c565b604082015262000f406060840162000e8c565b60608201525092915050565b60006001600160401b0382111562000f685762000f6862000dcd565b5060051b60200190565b8051801515811462000ea457600080fd5b805161ffff8116811462000ea457600080fd5b805163ffffffff8116811462000ea457600080fd5b80516001600160e01b03198116811462000ea457600080fd5b600082601f83011262000fd657600080fd5b8151602062000fef62000fe98362000f4c565b62000e59565b82815261024092830285018201928282019190878511156200101057600080fd5b8387015b85811015620011d257808903828112156200102f5760008081fd5b6200103962000de3565b620010448362000ea9565b815261022080601f19840112156200105c5760008081fd5b6200106662000e0e565b92506200107588850162000f72565b835260406200108681860162000f83565b8985015260606200109981870162000f96565b8286015260809150620010ae82870162000f96565b9085015260a0620010c186820162000f96565b8286015260c09150620010d682870162000f83565b9085015260e0620010e986820162000f96565b828601526101009150620010ff82870162000f83565b908501526101206200111386820162000f83565b8286015261014091506200112982870162000f83565b908501526101606200113d86820162000f96565b8286015261018091506200115382870162000f96565b908501526101a06200116786820162000ea9565b828601526101c091506200117d82870162000ea9565b908501526101e06200119186820162000f96565b828601526102009150620011a782870162000f72565b90850152620011b885830162000fab565b908401525080870191909152845292840192810162001014565b5090979650505050505050565b600082601f830112620011f157600080fd5b815160206200120462000fe98362000f4c565b82815260069290921b840181019181810190868411156200122457600080fd5b8286015b848110156200127a5760408189031215620012435760008081fd5b6200124d62000de3565b620012588262000e8c565b81526200126785830162000ea9565b8186015283529183019160400162001228565b509695505050505050565b600082601f8301126200129757600080fd5b81516020620012aa62000fe98362000f4c565b82815260059290921b84018101918181019086841115620012ca57600080fd5b8286015b848110156200127a5780516001600160401b0380821115620012ef57600080fd5b908801906040601f19838c0381018213156200130a57600080fd5b6200131462000de3565b6200132189860162000ea9565b815282850151848111156200133557600080fd5b8086019550508c603f8601126200134b57600080fd5b8885015193506200136062000fe98562000f4c565b84815260e09094028501830193898101908e8611156200137f57600080fd5b958401955b858710156200145857868f0360e08112156200139f57600080fd5b620013a962000de3565b620013b48962000e8c565b815260c08683011215620013c757600080fd5b620013d162000e34565b9150620013e08d8a0162000f96565b8252620013ef878a0162000f96565b8d8301526200140160608a0162000f83565b878301526200141360808a0162000f96565b60608301526200142660a08a0162000f96565b60808301526200143960c08a0162000f72565b60a0830152808d0191909152825260e09690960195908a019062001384565b828b015250875250505092840192508301620012ce565b60008060008060008587036101a08112156200148a57600080fd5b60c08112156200149957600080fd5b50620014a462000e34565b620014af8762000e8c565b8152620014bf6020880162000ea9565b602082015260408701516001600160601b0381168114620014df57600080fd5b6040820152620014f26060880162000e8c565b6060820152620015056080880162000e8c565b60808201526200151860a0880162000e8c565b60a082015294506200152e8760c0880162000ec1565b6101408701519094506001600160401b03808211156200154d57600080fd5b6200155b89838a0162000fc4565b94506101608801519150808211156200157357600080fd5b6200158189838a01620011df565b93506101808801519150808211156200159957600080fd5b50620015a88882890162001285565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c811660408601526200161360608601828560381c1663ffffffff169052565b6200162b60808601828560581c1663ffffffff169052565b6200164160a08601838560781c1661ffff169052565b6200165960c08601828560881c1663ffffffff169052565b6200166f60e08601838560a81c1661ffff169052565b620016866101008601838560b81c1661ffff169052565b6200169d6101208601838560c81c1661ffff169052565b620016b66101408601828560d81c1663ffffffff169052565b600186015463ffffffff8282161661016087015292506001600160401b03602084901c81166101808701529150620016ff6101a08601838560601c166001600160401b03169052565b620017186101c08601828560a01c1663ffffffff169052565b5050620017306101e0840160ff8360c01c1615159052565b60181b6001600160e01b03191661020083015260028301546001600160401b03166102208301526003909201546102409091015290565b8151151581526102208101602083015162001788602084018261ffff169052565b506040830151620017a1604084018263ffffffff169052565b506060830151620017ba606084018263ffffffff169052565b506080830151620017d3608084018263ffffffff169052565b5060a0830151620017ea60a084018261ffff169052565b5060c08301516200180360c084018263ffffffff169052565b5060e08301516200181a60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b03908116918501919091526101a080860151909116908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b60805160a05160c05160e051610100516101205161588e62001977600039600081816102da015281816111a0015261263b0152600081816102ab0152818161261301526134a601526000818161027c015281816125e90152612cf30152600081816102180152818161258401528181612ae001526135370152600081816101e90152818161255f01528181612fa50152613037015260008181610248015281816125b6015281816130f90152613169015261588e6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e9146108c4578063f2fde38b146108d7578063fbca3b74146108ea57600080fd5b8063a6f3ab6c1461089e578063ca643213146108b157600080fd5b80638da5cb5b116100b25780638da5cb5b146108675780639041be3d14610878578063a69c64c01461088b57600080fd5b806379ba5097146106fc57806382b49eb01461070457600080fd5b80633a019940116101245780636def4ce7116101095780636def4ce7146103b65780637437ff9f14610676578063770e2dc4146106e957600080fd5b80633a0199401461038157806348a98aa41461038b57600080fd5b8063061877e31461015657806306285c69146101a7578063181f5a771461031757806320487ded14610360575b600080fd5b6101896101643660046140bd565b6001600160a01b031660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61030a6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b60405161019e91906140da565b6103536040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161019e9190614196565b61037361036e3660046141e2565b61090a565b60405190815260200161019e565b610389610fa1565b005b61039e610399366004614232565b611165565b6040516001600160a01b03909116815260200161019e565b6106696103c436600461426b565b60408051610280810182526000606082018181526080830182905260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e083018290526102008301829052610220830182905261024083018290526102608301829052825260208201819052918101919091525067ffffffffffffffff908116600090815260066020908152604091829020825161028081018452815460ff80821615156060840190815261ffff6101008085048216608087015263ffffffff63010000008604811660a08801526701000000000000008604811660c08801526b0100000000000000000000008604811660e0808901919091526f010000000000000000000000000000008704841692880192909252710100000000000000000000000000000000008604811661012088015275010000000000000000000000000000000000000000008604831661014088015277010000000000000000000000000000000000000000000000860483166101608801527901000000000000000000000000000000000000000000000000008087049093166101808801527b0100000000000000000000000000000000000000000000000000000090950485166101a087015260018701548086166101c088015264010000000081048b166101e08801526c0100000000000000000000000081048b166102008801527401000000000000000000000000000000000000000081049095166102208701527801000000000000000000000000000000000000000000000000850490931615156102408601526001600160e01b0319930490911b919091166102608301528152600282015490941691840191909152600301549082015290565b60405161019e91906143ce565b6106dc60408051608081018252600080825260208201819052918101829052606081019190915250604080516080810182526002546001600160a01b03908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161019e9190614407565b6103896106f7366004614617565b611214565b61038961122a565b610807610712366004614232565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff9190911660009081526008602090815260408083206001600160a01b0394909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b60405161019e9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b6000546001600160a01b031661039e565b61018961088636600461426b565b6112f3565b610389610899366004614891565b61131f565b6103896108ac36600461494f565b611333565b6103896108bf3660046149ec565b611344565b6103736108d2366004614bfc565b611355565b6103896108e53660046140bd565b6117ca565b6108fd6108f836600461426b565b6117db565b60405161019e9190614c68565b67ffffffffffffffff82166000908152600660205260408120805460ff1661096f576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024015b60405180910390fd5b6109a0846109806020860186614cb5565b905061098f6040870187614d03565b905061099b8780614cb5565b61180f565b60006007816109b560808701606088016140bd565b6001600160a01b03168152602081019190915260400160009081205467ffffffffffffffff169150819003610a32576109f460808501606086016140bd565b6040517fa7499d200000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b60035460009081906001600160a01b031663ffdb4b37610a586080890160608a016140bd565b6040516001600160e01b031960e084901b1681526001600160a01b03909116600482015267ffffffffffffffff8a1660248201526044016040805180830381865afa158015610aab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acf9190614d79565b90925090506000808080610ae660408b018b614d03565b90501115610b2157610b158a610b0260808c0160608d016140bd565b87610b1060408e018e614d03565b611937565b91945092509050610b58565b6001870154610b559074010000000000000000000000000000000000000000900463ffffffff16662386f26fc10000614dd2565b92505b865460009077010000000000000000000000000000000000000000000000900461ffff1615610bc157610bbe8b6dffffffffffffffffffffffffffff607088901c16610ba760208e018e614cb5565b9050610bb660408f018f614d03565b905086611d28565b90505b875460009063ffffffff8516906f01000000000000000000000000000000900461ffff16610bf260208e018e614cb5565b610bfd929150614dd2565b8a54610c1e91906b010000000000000000000000900463ffffffff16614de9565b610c289190614de9565b9050610ee5610c3a60808d018d614cb5565b8b604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050611e2e565b51610ef09082614de9565b60018a01549091506000906c01000000000000000000000000900467ffffffffffffffff16610f2f836dffffffffffffffffffffffffffff8a16614dd2565b610f399190614dd2565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff88168382610f7067ffffffffffffffff8d168a614dd2565b610f7a9190614de9565b610f849190614de9565b610f8e9190614dfc565b9a50505050505050505050505b92915050565b600354604080517fcdc73d5100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163cdc73d5191600480830192869291908290030181865afa158015611003573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261102b9190810190614e37565b6005549091506001600160a01b031660005b825181101561116057600083828151811061105a5761105a614ec6565b60209081029190910101516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156110c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ec9190614ef5565b90508015611156576111086001600160a01b0383168583611ee9565b816001600160a01b0316846001600160a01b03167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161114d91815260200190565b60405180910390a35b505060010161103d565b505050565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156111e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120d9190614f0e565b9392505050565b61121c611f69565b6112268282611fc5565b5050565b6001546001600160a01b031633146112845760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610966565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120600201549091610f9b91166001614f2b565b611327611f69565b611330816123a5565b50565b61133b611f69565b61133081612482565b61134c611f69565b6113308161269b565b67ffffffffffffffff841660009081526006602052604081208161137c8288888888612c40565b905060005b8160e001515181101561176657600061139d6040890189614d03565b838181106113ad576113ad614ec6565b9050604002018036038101906113c39190614f53565b90508060200151600003611403576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006114138a8360000151611165565b90506001600160a01b03811615806114c957506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf0000000000000000000000000000000000000000000000000000000060048201526001600160a01b038216906301ffc9a790602401602060405180830381865afa1580156114a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c79190614f8d565b155b1561150e5781516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b6000816001600160a01b0316639a4575b96040518060a001604052808d806000019061153a9190614cb5565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525067ffffffffffffffff8f166020808301919091526001600160a01b03808e16604080850191909152918901516060840152885116608090920191909152516001600160e01b031960e084901b1681526115cd9190600401614faa565b6000604051808303816000875af11580156115ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116149190810190615077565b9050602081602001515111156116b75767ffffffffffffffff8b16600090815260086020908152604080832086516001600160a01b0316845282529091205490820151516e01000000000000000000000000000090910463ffffffff1610156116b75782516040517f36f536ca0000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b600186015481516116e891790100000000000000000000000000000000000000000000000000900460e01b906139d7565b60408051608081019091526001600160a01b03831660a08201528060c081016040516020818303038152906040528152602001826000015181526020018260200151815260200184602001518152508560e00151858151811061174d5761174d614ec6565b6020026020010181905250505050806001019050611381565b50611775818360030154613a11565b81515260405167ffffffffffffffff8816907f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29906117b49084906151ac565b60405180910390a251519150505b949350505050565b6117d2611f69565b61133081613af3565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8516600090815260066020526040902080546301000000900463ffffffff168511156118885780546040517f86933789000000000000000000000000000000000000000000000000000000008152630100000090910463ffffffff16600482015260248101869052604401610966565b8054610100900461ffff168411156118cc576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154604080516020601f860181900481028201810190925284815261192f92790100000000000000000000000000000000000000000000000000900460e01b9186908690819084018382808284376000920191909152506139d792505050565b505050505050565b6000808083815b81811015611d1b57600087878381811061195a5761195a614ec6565b9050604002018036038101906119709190614f53565b905060006001600160a01b031661198b8c8360000151611165565b6001600160a01b0316036119d95780516040517fbf16aab60000000000000000000000000000000000000000000000000000000081526001600160a01b039091166004820152602401610966565b67ffffffffffffffff8b16600090815260086020908152604080832084516001600160a01b03168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052611b475767ffffffffffffffff8c1660009081526006602052604090208054611ae790790100000000000000000000000000000000000000000000000000900461ffff16662386f26fc10000614dd2565b611af19089614de9565b8154909850611b25907b01000000000000000000000000000000000000000000000000000000900463ffffffff16886152c2565b6001820154909750611b3d9063ffffffff16876152c2565b9550505050611d13565b604081015160009061ffff1615611c635760008c6001600160a01b031684600001516001600160a01b031614611c065760035484516040517f4ab35b0b0000000000000000000000000000000000000000000000000000000081526001600160a01b039182166004820152911690634ab35b0b90602401602060405180830381865afa158015611bdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bff91906152df565b9050611c09565b508a5b620186a0836040015161ffff16611c4b8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613bb490919063ffffffff16565b611c559190614dd2565b611c5f9190614dfc565b9150505b6060820151611c7290886152c2565b9650816080015186611c8491906152c2565b8251909650600090611ca39063ffffffff16662386f26fc10000614dd2565b905080821015611cc257611cb7818a614de9565b985050505050611d13565b6000836020015163ffffffff16662386f26fc10000611ce19190614dd2565b905080831115611d0157611cf5818b614de9565b99505050505050611d13565b611d0b838b614de9565b995050505050505b60010161193e565b5050955095509592505050565b60008063ffffffff8316611d3d60e086614dd2565b611d49876101c0614de9565b611d539190614de9565b611d5d9190614de9565b67ffffffffffffffff8816600090815260066020526040812080549293509171010000000000000000000000000000000000810463ffffffff1690611dbf907501000000000000000000000000000000000000000000900461ffff1685614dd2565b611dc99190614de9565b825490915077010000000000000000000000000000000000000000000000900461ffff16611e076dffffffffffffffffffffffffffff8a1683614dd2565b611e119190614dd2565b611e2190655af3107a4000614dd2565b9998505050505050505050565b60408051808201909152600080825260208201526000611e548585856101800151613bf1565b9050826060015163ffffffff1681600001511115611e9e576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015611eb257508060200151155b156117c2576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052611160908490613d6a565b6000546001600160a01b03163314611fc35760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610966565b565b60005b82518110156122ce576000838281518110611fe557611fe5614ec6565b6020026020010151905060008160000151905060005b8260200151518110156122c05760008360200151828151811061202057612020614ec6565b602002602001015160200151905060008460200151838151811061204657612046614ec6565b60200260200101516000015190506020826080015163ffffffff1610156120b65760808201516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526001600160a01b038316600482015263ffffffff9091166024820152604401610966565b67ffffffffffffffff841660008181526008602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906122ae908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101611ffb565b505050806001019050611fc8565b5060005b81518110156111605760008282815181106122ef576122ef614ec6565b6020026020010151600001519050600083838151811061231157612311614ec6565b60209081029190910181015181015167ffffffffffffffff841660008181526008845260408082206001600160a01b038516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a350506001016122d2565b60005b81518110156112265760008282815181106123c5576123c5614ec6565b602002602001015160000151905060008383815181106123e7576123e7614ec6565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016123a8565b60208101516001600160a01b031615806124a7575060608101516001600160a01b0316155b156124de576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556020808401516003805484169185169190911790556040808501516004805485169186169190911790556060808601516005805490951690861617909355805160c0810182527f0000000000000000000000000000000000000000000000000000000000000000851681527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff16928101929092527f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16828201527f00000000000000000000000000000000000000000000000000000000000000008416928201929092527f0000000000000000000000000000000000000000000000000000000000000000831660808201527f000000000000000000000000000000000000000000000000000000000000000090921660a0830152517f4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa916126909184906152fa565b60405180910390a150565b60005b81518110156112265760008282815181106126bb576126bb614ec6565b6020026020010151905060008383815181106126d9576126d9614ec6565b60200260200101516000015190508067ffffffffffffffff166000148061271157506020820151610180015167ffffffffffffffff16155b8061274f5750602082015161020001516001600160e01b0319167f2812d52c0000000000000000000000000000000000000000000000000000000014155b15612792576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610966565b6000600660008367ffffffffffffffff1667ffffffffffffffff168152602001908152602001600020905060006040518060600160405280856020015181526020018360020160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1681526020018360030154815250905080600001518260000160008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160146101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160186101000a81548160ff0219169083151502179055506102008201518160010160196101000a81548163ffffffff021916908360e01c021790555090505081600301546000801b03612b8657604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908416606082015230608082015260a00160408051601f19818403018152918152815160209092019190912082820181905260038401555167ffffffffffffffff8416907f26f8c55bd3f591fd6042c98ad4d707257cd565dc47609bfa3ba517400d05704490612b799085906153a3565b60405180910390a2612c31565b60208460200151610160015163ffffffff161015612bea57602084015161016001516040517f24ecdc020000000000000000000000000000000000000000000000000000000081526000600482015263ffffffff9091166024820152604401610966565b8267ffffffffffffffff167fd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb8560200151604051612c289190615537565b60405180910390a25b5050505080600101905061269e565b604080516101a08101825260006101008201818152610120830182905261014083018290526101608301829052610180830182905282526020820181905260609282018390528282018390526080820183905260a0820181905260c082015260e08101919091526040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608086901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612d42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d669190614f8d565b15612da9576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610966565b6001600160a01b038216612de9576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002546001600160a01b03163314612e2d576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b855460ff16612e74576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610966565b6000612e836040860186614d03565b9150612ea5905086612e986020880188614cb5565b90508361099b8980614cb5565b8015612f99576004546001600160a01b03168015612f97576040517fe0a0e5060000000000000000000000000000000000000000000000000000000081526001600160a01b0382169063e0a0e50690612f04908a908a9060040161560a565b600060405180830381600087803b158015612f1e57600080fd5b505af1925050508015612f2f575060015b612f97573d808015612f5d576040519150601f19603f3d011682016040523d82523d6000602084013e612f62565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016109669190614196565b505b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016612fd560808801606089016140bd565b6001600160a01b031603612fea5750836130a5565b6003546001600160a01b03166241e5be61300a6080890160608a016140bd565b60405160e083901b6001600160e01b03191681526001600160a01b039182166004820152602481018990527f00000000000000000000000000000000000000000000000000000000000000009091166044820152606401602060405180830381865afa15801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a29190614ef5565b90505b6130b560808701606088016140bd565b6001600160a01b03167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f826040516130ef91815260200190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16811115613196576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018290526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610966565b60006134566131a86080890189614cb5565b8b600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050611e2e565b60200151613516576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff891660048201526001600160a01b0386811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af11580156134ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135139190615728565b90505b604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528b811661014085015260028d0180549394938493926101608501929187916135869116615745565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff1681526020018567ffffffffffffffff168152508152602001876001600160a01b031681526020018980602001906135ec9190614cb5565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016136308a80614cb5565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161392861367a60808c018c614cb5565b8e600001604051806102200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900461ffff1661ffff1661ffff1681526020016000820160039054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160079054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600b9054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600f9054906101000a900461ffff1661ffff1661ffff1681526020016000820160119054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160159054906101000a900461ffff1661ffff1661ffff1681526020016000820160179054906101000a900461ffff1661ffff1661ffff1681526020016000820160199054906101000a900461ffff1661ffff1661ffff16815260200160008201601b9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160049054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff16815260200160018201600c9054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016001820160149054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016001820160189054906101000a900460ff161515151581526020016001820160199054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525050613e4f565b815260200161393d60808b0160608c016140bd565b6001600160a01b031681526020018881526020018567ffffffffffffffff81111561396a5761396a614443565b6040519080825280602002602001820160405280156139c657816020015b6139b36040518060800160405280606081526020016060815260200160608152602001600081525090565b8152602001906001900390816139885790505b5090529a9950505050505050505050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b03198316016112265761116081613ecf565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001613a539695949392919061576c565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001613a8a91906157c0565b60408051601f1981840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b336001600160a01b03821603613b4b5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610966565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000670de0b6b3a7640000613be7837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616614dd2565b61120d9190614dfc565b60408051808201909152600080825260208201526000839003613c3257506040805180820190915267ffffffffffffffff821681526000602082015261120d565b6000613c3e84866157d3565b90506000613c4f8560048189615803565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050506001600160e01b031982167fe7e230f00000000000000000000000000000000000000000000000000000000001613cd45780806020019051810190613ccb919061582d565b9250505061120d565b7f6859a837000000000000000000000000000000000000000000000000000000006001600160e01b0319831601613d3857604051806040016040528082806020019051810190613d249190614ef5565b81526000602090910152925061120d915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000613dbf826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613f759092919063ffffffff16565b8051909150156111605780806020019051810190613ddd9190614f8d565b6111605760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610966565b6102008101516060907fd7ed2ad4000000000000000000000000000000000000000000000000000000006001600160e01b0319821601613ec757613e94858585611e2e565b6040805182516020808301919091529092015115159082015260600160405160208183030381529060405291505061120d565b509392505050565b60008151602014613f0e57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109669190614196565b600082806020019051810190613f249190614ef5565b90506001600160a01b03811180613f3c575061040081105b15610f9b57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016109669190614196565b60606117c2848460008585600080866001600160a01b03168587604051613f9c9190615865565b60006040518083038185875af1925050503d8060008114613fd9576040519150601f19603f3d011682016040523d82523d6000602084013e613fde565b606091505b5091509150613fef87838387613ffa565b979650505050505050565b60608315614069578251600003614062576001600160a01b0385163b6140625760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610966565b50816117c2565b6117c2838381511561407e5781518083602001fd5b8060405162461bcd60e51b81526004016109669190614196565b6001600160a01b038116811461133057600080fd5b80356140b881614098565b919050565b6000602082840312156140cf57600080fd5b813561120d81614098565b60c08101610f9b82846001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60005b83811015614161578181015183820152602001614149565b50506000910152565b60008151808452614182816020860160208601614146565b601f01601f19169290920160200192915050565b60208152600061120d602083018461416a565b67ffffffffffffffff8116811461133057600080fd5b80356140b8816141a9565b600060a082840312156141dc57600080fd5b50919050565b600080604083850312156141f557600080fd5b8235614200816141a9565b9150602083013567ffffffffffffffff81111561421c57600080fd5b614228858286016141ca565b9150509250929050565b6000806040838503121561424557600080fd5b8235614250816141a9565b9150602083013561426081614098565b809150509250929050565b60006020828403121561427d57600080fd5b813561120d816141a9565b80511515825260208101516142a3602084018261ffff169052565b5060408101516142bb604084018263ffffffff169052565b5060608101516142d3606084018263ffffffff169052565b5060808101516142eb608084018263ffffffff169052565b5060a081015161430160a084018261ffff169052565b5060c081015161431960c084018263ffffffff169052565b5060e081015161432f60e084018261ffff169052565b506101008181015161ffff9081169184019190915261012080830151909116908301526101408082015163ffffffff90811691840191909152610160808301518216908401526101808083015167ffffffffffffffff908116918501919091526101a080840151909116908401526101c080830151909116908301526101e080820151151590830152610200908101516001600160e01b031916910152565b6000610260820190506143e2828451614288565b602083015167ffffffffffffffff166102208301526040909201516102409091015290565b60808101610f9b828480516001600160a01b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561449557614495614443565b60405290565b60405160c0810167ffffffffffffffff8111828210171561449557614495614443565b604051610220810167ffffffffffffffff8111828210171561449557614495614443565b604051601f8201601f1916810167ffffffffffffffff8111828210171561450b5761450b614443565b604052919050565b600067ffffffffffffffff82111561452d5761452d614443565b5060051b60200190565b803563ffffffff811681146140b857600080fd5b803561ffff811681146140b857600080fd5b801515811461133057600080fd5b80356140b88161455d565b600082601f83011261458757600080fd5b8135602061459c61459783614513565b6144e2565b82815260069290921b840181019181810190868411156145bb57600080fd5b8286015b8481101561460c57604081890312156145d85760008081fd5b6145e0614472565b81356145eb816141a9565b8152818501356145fa81614098565b818601528352918301916040016145bf565b509695505050505050565b6000806040838503121561462a57600080fd5b67ffffffffffffffff8335111561464057600080fd5b83601f84358501011261465257600080fd5b6146626145978435850135614513565b8335840180358083526020808401939260059290921b9091010186101561468857600080fd5b602085358601015b85358601803560051b0160200181101561485b5767ffffffffffffffff813511156146ba57600080fd5b6040601f198235883589010189030112156146d457600080fd5b6146dc614472565b6146ef6020833589358a010101356141a9565b863587018235016020810135825267ffffffffffffffff604090910135111561471757600080fd5b86358701823501604081013501603f8101891361473357600080fd5b6147436145976020830135614513565b602082810135808352908201919060e00283016040018b101561476557600080fd5b604083015b604060e06020860135028501018110156148425760e0818d03121561478e57600080fd5b614796614472565b6147a08235614098565b8135815260c0601f19838f030112156147b857600080fd5b6147c061449b565b6147cc60208401614537565b81526147da60408401614537565b60208201526147eb6060840161454b565b60408201526147fc60808401614537565b606082015261480d60a08401614537565b608082015261481f60c084013561455d565b60c083013560a0820152602082810191909152908452929092019160e00161476a565b5060208481019190915292865250509283019201614690565b5092505067ffffffffffffffff6020840135111561487857600080fd5b6148888460208501358501614576565b90509250929050565b600060208083850312156148a457600080fd5b823567ffffffffffffffff8111156148bb57600080fd5b8301601f810185136148cc57600080fd5b80356148da61459782614513565b81815260069190911b820183019083810190878311156148f957600080fd5b928401925b82841015613fef57604084890312156149175760008081fd5b61491f614472565b843561492a81614098565b815284860135614939816141a9565b81870152825260409390930192908401906148fe565b60006080828403121561496157600080fd5b6040516080810181811067ffffffffffffffff8211171561498457614984614443565b604052823561499281614098565b815260208301356149a281614098565b602082015260408301356149b581614098565b604082015260608301356149c881614098565b60608201529392505050565b80356001600160e01b0319811681146140b857600080fd5b600060208083850312156149ff57600080fd5b823567ffffffffffffffff811115614a1657600080fd5b8301601f81018513614a2757600080fd5b8035614a3561459782614513565b8181526102409182028301840191848201919088841115614a5557600080fd5b938501935b83851015614bf05784890381811215614a735760008081fd5b614a7b614472565b8635614a86816141a9565b8152610220601f198301811315614a9d5760008081fd5b614aa56144be565b9250614ab289890161456b565b83526040614ac1818a0161454b565b8a8501526060614ad2818b01614537565b8286015260809150614ae5828b01614537565b9085015260a0614af68a8201614537565b8286015260c09150614b09828b0161454b565b9085015260e0614b1a8a8201614537565b828601526101009150614b2e828b0161454b565b90850152610120614b408a820161454b565b828601526101409150614b54828b0161454b565b90850152610160614b668a8201614537565b828601526101809150614b7a828b01614537565b908501526101a0614b8c8a82016141bf565b828601526101c09150614ba0828b016141bf565b908501526101e0614bb28a8201614537565b828601526102009150614bc6828b0161456b565b90850152614bd58983016149d4565b90840152508088019190915283529384019391850191614a5a565b50979650505050505050565b60008060008060808587031215614c1257600080fd5b8435614c1d816141a9565b9350602085013567ffffffffffffffff811115614c3957600080fd5b614c45878288016141ca565b935050604085013591506060850135614c5d81614098565b939692955090935050565b6020808252825182820181905260009190848201906040850190845b81811015614ca95783516001600160a01b031683529284019291840191600101614c84565b50909695505050505050565b6000808335601e19843603018112614ccc57600080fd5b83018035915067ffffffffffffffff821115614ce757600080fd5b602001915036819003821315614cfc57600080fd5b9250929050565b6000808335601e19843603018112614d1a57600080fd5b83018035915067ffffffffffffffff821115614d3557600080fd5b6020019150600681901b3603821315614cfc57600080fd5b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146140b857600080fd5b60008060408385031215614d8c57600080fd5b614d9583614d4d565b915061488860208401614d4d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f9b57610f9b614da3565b80820180821115610f9b57610f9b614da3565b600082614e32577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020808385031215614e4a57600080fd5b825167ffffffffffffffff811115614e6157600080fd5b8301601f81018513614e7257600080fd5b8051614e8061459782614513565b81815260059190911b82018301908381019087831115614e9f57600080fd5b928401925b82841015613fef578351614eb781614098565b82529284019290840190614ea4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215614f0757600080fd5b5051919050565b600060208284031215614f2057600080fd5b815161120d81614098565b67ffffffffffffffff818116838216019080821115614f4c57614f4c614da3565b5092915050565b600060408284031215614f6557600080fd5b614f6d614472565b8235614f7881614098565b81526020928301359281019290925250919050565b600060208284031215614f9f57600080fd5b815161120d8161455d565b602081526000825160a06020840152614fc660c084018261416a565b905067ffffffffffffffff602085015116604084015260408401516001600160a01b038082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600082601f83011261502457600080fd5b815167ffffffffffffffff81111561503e5761503e614443565b6150516020601f19601f840116016144e2565b81815284602083860101111561506657600080fd5b6117c2826020830160208701614146565b60006020828403121561508957600080fd5b815167ffffffffffffffff808211156150a157600080fd5b90830190604082860312156150b557600080fd5b6150bd614472565b8251828111156150cc57600080fd5b6150d887828601615013565b8252506020830151828111156150ed57600080fd5b6150f987828601615013565b60208301525095945050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561519f57601f1986840301895281516080815181865261514b8287018261416a565b9150508582015185820387870152615163828261416a565b9150506040808301518683038288015261517d838261416a565b6060948501519790940196909652505098840198925090830190600101615125565b5090979650505050505050565b602081526151fd60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161521960c08401826001600160a01b03169052565b5060408301516101808060e08501526152366101a085018361416a565b91506060850151601f198086850301610100870152615255848361416a565b9350608087015191508086850301610120870152615273848361416a565b935060a087015191506152926101408701836001600160a01b03169052565b60c087015161016087015260e08701519150808685030183870152506152b88382615108565b9695505050505050565b63ffffffff818116838216019080821115614f4c57614f4c614da3565b6000602082840312156152f157600080fd5b61120d82614d4d565b610140810161536782856001600160a01b0380825116835267ffffffffffffffff60208301511660208401526bffffffffffffffffffffffff60408301511660408401528060608301511660608401528060808301511660808401528060a08301511660a0840152505050565b82516001600160a01b0390811660c08401526020840151811660e08401526040840151811661010084015260608401511661012083015261120d565b815460ff81161515825261026082019061ffff600882901c8116602085015263ffffffff601883901c811660408601526153ea60608601828560381c1663ffffffff169052565b61540160808601828560581c1663ffffffff169052565b61541660a08601838560781c1661ffff169052565b61542d60c08601828560881c1663ffffffff169052565b61544260e08601838560a81c1661ffff169052565b6154586101008601838560b81c1661ffff169052565b61546e6101208601838560c81c1661ffff169052565b6154866101408601828560d81c1663ffffffff169052565b600186015463ffffffff82821616610160870152925067ffffffffffffffff602084901c811661018087015291506154d06101a08601838560601c1667ffffffffffffffff169052565b6154e86101c08601828560a01c1663ffffffff169052565b50506154ff6101e0840160ff8360c01c1615159052565b60181b6001600160e01b031916610200830152600283015467ffffffffffffffff166102208301526003909201546102409091015290565b6102208101610f9b8284614288565b6000808335601e1984360301811261555d57600080fd5b830160208101925035905067ffffffffffffffff81111561557d57600080fd5b803603821315614cfc57600080fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8183526000602080850194508260005b858110156155ff5781356155da81614098565b6001600160a01b031687528183013583880152604096870196909101906001016155c7565b509495945050505050565b600067ffffffffffffffff80851683526040602084015261562b8485615546565b60a0604086015261564060e08601828461558c565b9150506156506020860186615546565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087850301606088015261568684838561558c565b935060408801359250601e198836030183126156a157600080fd5b602092880192830192359150848211156156ba57600080fd5b8160061b36038313156156cc57600080fd5b808785030160808801526156e18483856155b7565b94506156ef606089016140ad565b6001600160a01b03811660a0890152935061570d6080890189615546565b94509250808786030160c08801525050613fef83838361558c565b60006020828403121561573a57600080fd5b815161120d816141a9565b600067ffffffffffffffff80831681810361576257615762614da3565b6001019392505050565b60006001600160a01b03808916835260c0602084015261578f60c084018961416a565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061120d6020830184615108565b6001600160e01b031981358181169160048510156157fb5780818660040360031b1b83161692505b505092915050565b6000808585111561581357600080fd5b8386111561582057600080fd5b5050820193919092039150565b60006040828403121561583f57600080fd5b615847614472565b8251815260208301516158598161455d565b60208201529392505050565b60008251615877818460208701614146565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"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\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"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\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162003161380380620031618339810160408190526200003591620003db565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200017a565b505082516001600160401b031615905080620000e6575060208201516001600160a01b0316155b80620000fd575060408201516001600160a01b0316155b8062000114575060608201516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b81516001600160401b031660805260208201516001600160a01b0390811660a0526040830151811660c05260608301511660e052620001728162000225565b5050620004d1565b336001600160a01b03821603620001d45760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60208101516001600160a01b031615806200024b575060608101516001600160a01b0316155b156200026a576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b604051608081016001600160401b0381118282101715620003b857634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b0381168114620003d657600080fd5b919050565b600080828403610100811215620003f157600080fd5b60808112156200040057600080fd5b6200040a62000387565b84516001600160401b03811681146200042257600080fd5b81526200043260208601620003be565b60208201526200044560408601620003be565b60408201526200045860608601620003be565b606082015292506080607f19820112156200047257600080fd5b506200047d62000387565b6200048b60808501620003be565b81526200049b60a08501620003be565b6020820152620004ae60c08501620003be565b6040820152620004c160e08501620003be565b6060820152809150509250929050565b60805160a05160c05160e051612c176200054a600039600081816101c00152818161081b015261147901526000818161018401528181610d3801526114520152600081816101480152818161044e015261142801526000818161011801528181610c55015281816110ee01526113fb0152612c176000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c806379ba50971161008c578063a6f3ab6c11610066578063a6f3ab6c14610391578063df0aa9e9146103a4578063f2fde38b146103b7578063fbca3b74146103ca57600080fd5b806379ba50971461033f5780638da5cb5b146103475780639041be3d1461036557600080fd5b80633a019940116100bd5780633a0199401461027d57806348a98aa4146102875780637437ff9f146102bf57600080fd5b806306285c69146100e4578063181f5a771461021357806320487ded1461025c575b600080fd5b6101fd60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161020a9190611cf8565b60405180910390f35b61024f6040518060400160405280601c81526020017f45564d3245564d4d756c74694f6e52616d7020312e362e302d6465760000000081525081565b60405161020a9190611dbd565b61026f61026a366004611dfe565b6103ea565b60405190815260200161020a565b6102856105a3565b005b61029a610295366004611e70565b6107d3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161020a565b610332604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161020a9190611ea9565b610285610888565b60005473ffffffffffffffffffffffffffffffffffffffff1661029a565b610378610373366004611ef2565b610985565b60405167ffffffffffffffff909116815260200161020a565b61028561039f366004611fc6565b6109ae565b61026f6103b236600461204b565b6109c2565b6102856103c53660046120b7565b6111a2565b6103dd6103d8366004611ef2565b6111b3565b60405161020a91906120d4565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610495573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b9919061213e565b15610501576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6003546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd90610559908690869060040161226d565b602060405180830381865afa158015610576573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059a91906123b6565b90505b92915050565b600354604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610612573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261065891908101906123cf565b60055490915073ffffffffffffffffffffffffffffffffffffffff1660005b82518110156107ce57600083828151811061069457610694612481565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa15801561070f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073391906123b6565b905080156107c45761075c73ffffffffffffffffffffffffffffffffffffffff831685836111e7565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e836040516107bb91815260200190565b60405180910390a35b5050600101610677565b505050565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610864573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059a91906124b0565b60015473ffffffffffffffffffffffffffffffffffffffff163314610909576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016104f8565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161059d911660016124fc565b6109b6611274565b6109bf816112f7565b50565b600073ffffffffffffffffffffffffffffffffffffffff8216610a11576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025473ffffffffffffffffffffffffffffffffffffffff163314610a62576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045473ffffffffffffffffffffffffffffffffffffffff168015610b08576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610ad5908990899060040161226d565b600060405180830381600087803b158015610aef57600080fd5b505af1158015610b03573d6000803e3d6000fd5b505050505b6003546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a610b3e60808c0160608d016120b7565b8a610b4c60808e018e612524565b6040518663ffffffff1660e01b8152600401610b6c959493929190612589565b600060405180830381865afa158015610b89573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610bcf9190810190612651565b91945092509050610be66080890160608a016120b7565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f84604051610c2d91815260200190565b60405180910390a2604080516101a0810182526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528d8116610140850181905283526006602052938220805492948493610160850192918791610caa91166126a8565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186610daa576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015610d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da591906126cf565b610dad565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a8060200190610deb9190612524565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610e2f8b80612524565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610e7660808c018c612524565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610ec060808c0160608d016120b7565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190610ef191906126ec565b905067ffffffffffffffff811115610f0b57610f0b611f0f565b604051908082528060200260200182016040528015610f6757816020015b610f546040518060800160405280606081526020016060815260200160608152602001600081525090565b815260200190600190039081610f295790505b509052905060005b610f7c60408b018b6126ec565b905081101561102b57611002610f9560408c018c6126ec565b83818110610fa557610fa5612481565b905060400201803603810190610fbb9190612754565b8c610fc68d80612524565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506114dc915050565b8260e00151828151811061101857611018612481565b6020908102919091010152600101610f6f565b5060035460e082015173ffffffffffffffffffffffffffffffffffffffff9091169063cc88924c908c9061106260408e018e6126ec565b6040518563ffffffff1660e01b81526004016110819493929190612850565b60006040518083038186803b15801561109957600080fd5b505afa1580156110ad573d6000803e3d6000fd5b505050506080808201839052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c166060820152309181019190915261114a90829060a001604051602081830303815290604052805190602001206117e6565b81515260405167ffffffffffffffff8b16907f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab2990611189908490612886565b60405180910390a251519450505050505b949350505050565b6111aa611274565b6109bf816118e6565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526107ce9084906119db565b60005473ffffffffffffffffffffffffffffffffffffffff1633146112f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016104f8565b565b602081015173ffffffffffffffffffffffffffffffffffffffff1615806113365750606081015173ffffffffffffffffffffffffffffffffffffffff16155b1561136d576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32916114d19184906129d4565b60405180910390a150565b6115076040518060800160405280606081526020016060815260200160608152602001600081525090565b8460200151600003611545576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006115558587600001516107d3565b905073ffffffffffffffffffffffffffffffffffffffff8116158061162557506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa1580156115ff573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611623919061213e565b155b156116775785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016104f8565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b81526004016117169190612a73565b6000604051808303816000875af1158015611735573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261177b9190810190612ae9565b604080516080810190915273ffffffffffffffffffffffffffffffffffffffff841660a08201529091508060c0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c0015160405160200161182896959493929190612b7a565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161185f9190612bdb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603611965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016104f8565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611a3d826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ae79092919063ffffffff16565b8051909150156107ce5780806020019051810190611a5b919061213e565b6107ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016104f8565b6060611af68484600085611b00565b90505b9392505050565b606082471015611b92576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016104f8565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611bbb9190612bee565b60006040518083038185875af1925050503d8060008114611bf8576040519150601f19603f3d011682016040523d82523d6000602084013e611bfd565b606091505b5091509150611c0e87838387611c19565b979650505050505050565b60608315611caf578251600003611ca85773ffffffffffffffffffffffffffffffffffffffff85163b611ca8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104f8565b508161119a565b61119a8383815115611cc45781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104f89190611dbd565b6080810161059d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b83811015611d6a578181015183820152602001611d52565b50506000910152565b60008151808452611d8b816020860160208601611d4f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061059a6020830184611d73565b67ffffffffffffffff811681146109bf57600080fd5b600060a08284031215611df857600080fd5b50919050565b60008060408385031215611e1157600080fd5b8235611e1c81611dd0565b9150602083013567ffffffffffffffff811115611e3857600080fd5b611e4485828601611de6565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff811681146109bf57600080fd5b60008060408385031215611e8357600080fd5b8235611e8e81611dd0565b91506020830135611e9e81611e4e565b809150509250929050565b6080810161059d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b600060208284031215611f0457600080fd5b8135611af981611dd0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611f6157611f61611f0f565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611fae57611fae611f0f565b604052919050565b8035611fc181611e4e565b919050565b600060808284031215611fd857600080fd5b6040516080810181811067ffffffffffffffff82111715611ffb57611ffb611f0f565b604052823561200981611e4e565b8152602083013561201981611e4e565b6020820152604083013561202c81611e4e565b6040820152606083013561203f81611e4e565b60608201529392505050565b6000806000806080858703121561206157600080fd5b843561206c81611dd0565b9350602085013567ffffffffffffffff81111561208857600080fd5b61209487828801611de6565b9350506040850135915060608501356120ac81611e4e565b939692955090935050565b6000602082840312156120c957600080fd5b8135611af981611e4e565b6020808252825182820181905260009190848201906040850190845b8181101561212257835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016120f0565b50909695505050505050565b80518015158114611fc157600080fd5b60006020828403121561215057600080fd5b61059a8261212e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261218e57600080fd5b830160208101925035905067ffffffffffffffff8111156121ae57600080fd5b8036038213156121bd57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b8581101561226257813561223081611e4e565b73ffffffffffffffffffffffffffffffffffffffff16875281830135838801526040968701969091019060010161221d565b509495945050505050565b600067ffffffffffffffff80851683526040602084015261228e8485612159565b60a060408601526122a360e0860182846121c4565b9150506122b36020860186612159565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808785030160608801526122e98483856121c4565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe188360301831261232257600080fd5b6020928801928301923591508482111561233b57600080fd5b8160061b360383131561234d57600080fd5b8087850301608088015261236284838561220d565b945061237060608901611fb6565b73ffffffffffffffffffffffffffffffffffffffff811660a0890152935061239b6080890189612159565b94509250808786030160c08801525050611c0e8383836121c4565b6000602082840312156123c857600080fd5b5051919050565b600060208083850312156123e257600080fd5b825167ffffffffffffffff808211156123fa57600080fd5b818501915085601f83011261240e57600080fd5b81518181111561242057612420611f0f565b8060051b9150612431848301611f67565b818152918301840191848101908884111561244b57600080fd5b938501935b83851015612475578451925061246583611e4e565b8282529385019390850190612450565b98975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156124c257600080fd5b8151611af981611e4e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561251d5761251d6124cd565b5092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261255957600080fd5b83018035915067ffffffffffffffff82111561257457600080fd5b6020019150368190038213156121bd57600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000611c0e6080830184866121c4565b600082601f8301126125e057600080fd5b815167ffffffffffffffff8111156125fa576125fa611f0f565b61262b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611f67565b81815284602083860101111561264057600080fd5b61119a826020830160208701611d4f565b60008060006060848603121561266657600080fd5b835192506126766020850161212e565b9150604084015167ffffffffffffffff81111561269257600080fd5b61269e868287016125cf565b9150509250925092565b600067ffffffffffffffff8083168181036126c5576126c56124cd565b6001019392505050565b6000602082840312156126e157600080fd5b8151611af981611dd0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261272157600080fd5b83018035915067ffffffffffffffff82111561273c57600080fd5b6020019150600681901b36038213156121bd57600080fd5b60006040828403121561276657600080fd5b61276e611f3e565b823561277981611e4e565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015612843577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08684030189528151608081518186526127ef82870182611d73565b91505085820151858203878701526128078282611d73565b915050604080830151868303828801526128218382611d73565b60609485015197909401969096525050988401989250908301906001016127ab565b5090979650505050505050565b67ffffffffffffffff85168152606060208201526000612873606083018661278e565b8281036040840152611c0e81858761220d565b602081526128d760208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161290060c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e085015261291d6101a0850183611d73565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261295a8483611d73565b93506080870151915080868503016101208701526129788483611d73565b935060a087015191506129a461014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506129ca838261278e565b9695505050505050565b6101008101612a2c828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611af9565b602081526000825160a06020840152612a8f60c0840182611d73565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600060208284031215612afb57600080fd5b815167ffffffffffffffff80821115612b1357600080fd5b9083019060408286031215612b2757600080fd5b612b2f611f3e565b825182811115612b3e57600080fd5b612b4a878286016125cf565b825250602083015182811115612b5f57600080fd5b612b6b878286016125cf565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c06020840152612baa60c0840189611d73565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061059a602083018461278e565b60008251612c00818460208701611d4f565b919091019291505056fea164736f6c6343000818000a", } var EVM2EVMMultiOnRampABI = EVM2EVMMultiOnRampMetaData.ABI var EVM2EVMMultiOnRampBin = EVM2EVMMultiOnRampMetaData.Bin -func DeployEVM2EVMMultiOnRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMMultiOnRampStaticConfig, dynamicConfig EVM2EVMMultiOnRampDynamicConfig, destChainConfigArgs []EVM2EVMMultiOnRampDestChainConfigArgs, premiumMultiplierWeiPerEthArgs []EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthArgs, tokenTransferFeeConfigArgs []EVM2EVMMultiOnRampTokenTransferFeeConfigArgs) (common.Address, *types.Transaction, *EVM2EVMMultiOnRamp, error) { +func DeployEVM2EVMMultiOnRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMMultiOnRampStaticConfig, dynamicConfig EVM2EVMMultiOnRampDynamicConfig) (common.Address, *types.Transaction, *EVM2EVMMultiOnRamp, error) { parsed, err := EVM2EVMMultiOnRampMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -163,7 +101,7 @@ func DeployEVM2EVMMultiOnRamp(auth *bind.TransactOpts, backend bind.ContractBack return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EVM2EVMMultiOnRampBin), backend, staticConfig, dynamicConfig, destChainConfigArgs, premiumMultiplierWeiPerEthArgs, tokenTransferFeeConfigArgs) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EVM2EVMMultiOnRampBin), backend, staticConfig, dynamicConfig) if err != nil { return common.Address{}, nil, nil, err } @@ -286,28 +224,6 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorRaw) Transact(opts *bind. return _EVM2EVMMultiOnRamp.Contract.contract.Transact(opts, method, params...) } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (EVM2EVMMultiOnRampDestChainConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) - - if err != nil { - return *new(EVM2EVMMultiOnRampDestChainConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOnRampDestChainConfig)).(*EVM2EVMMultiOnRampDestChainConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetDestChainConfig(destChainSelector uint64) (EVM2EVMMultiOnRampDestChainConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetDestChainConfig(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetDestChainConfig(destChainSelector uint64) (EVM2EVMMultiOnRampDestChainConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetDestChainConfig(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector) -} - func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampDynamicConfig, error) { var out []interface{} err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getDynamicConfig") @@ -396,28 +312,6 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetPoolBySourceToken return _EVM2EVMMultiOnRamp.Contract.GetPoolBySourceToken(&_EVM2EVMMultiOnRamp.CallOpts, arg0, sourceToken) } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getPremiumMultiplierWeiPerEth", token) - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { - return _EVM2EVMMultiOnRamp.Contract.GetPremiumMultiplierWeiPerEth(&_EVM2EVMMultiOnRamp.CallOpts, token) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { - return _EVM2EVMMultiOnRamp.Contract.GetPremiumMultiplierWeiPerEth(&_EVM2EVMMultiOnRamp.CallOpts, token) -} - func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetStaticConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampStaticConfig, error) { var out []interface{} err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getStaticConfig") @@ -462,28 +356,6 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetSupportedTokens(a return _EVM2EVMMultiOnRamp.Contract.GetSupportedTokens(&_EVM2EVMMultiOnRamp.CallOpts, arg0) } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (EVM2EVMMultiOnRampTokenTransferFeeConfig, error) { - var out []interface{} - err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "getTokenTransferFeeConfig", destChainSelector, token) - - if err != nil { - return *new(EVM2EVMMultiOnRampTokenTransferFeeConfig), err - } - - out0 := *abi.ConvertType(out[0], new(EVM2EVMMultiOnRampTokenTransferFeeConfig)).(*EVM2EVMMultiOnRampTokenTransferFeeConfig) - - return out0, err - -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (EVM2EVMMultiOnRampTokenTransferFeeConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetTokenTransferFeeConfig(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector, token) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCallerSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (EVM2EVMMultiOnRampTokenTransferFeeConfig, error) { - return _EVM2EVMMultiOnRamp.Contract.GetTokenTransferFeeConfig(&_EVM2EVMMultiOnRamp.CallOpts, destChainSelector, token) -} - func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _EVM2EVMMultiOnRamp.contract.Call(opts, &out, "owner") @@ -540,42 +412,6 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) AcceptOwnership( return _EVM2EVMMultiOnRamp.Contract.AcceptOwnership(&_EVM2EVMMultiOnRamp.TransactOpts) } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []EVM2EVMMultiOnRampDestChainConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) ApplyDestChainConfigUpdates(destChainConfigArgs []EVM2EVMMultiOnRampDestChainConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ApplyDestChainConfigUpdates(&_EVM2EVMMultiOnRamp.TransactOpts, destChainConfigArgs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) ApplyDestChainConfigUpdates(destChainConfigArgs []EVM2EVMMultiOnRampDestChainConfigArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ApplyDestChainConfigUpdates(&_EVM2EVMMultiOnRamp.TransactOpts, destChainConfigArgs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "applyPremiumMultiplierWeiPerEthUpdates", premiumMultiplierWeiPerEthArgs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_EVM2EVMMultiOnRamp.TransactOpts, premiumMultiplierWeiPerEthArgs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_EVM2EVMMultiOnRamp.TransactOpts, premiumMultiplierWeiPerEthArgs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []EVM2EVMMultiOnRampTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []EVM2EVMMultiOnRampTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.contract.Transact(opts, "applyTokenTransferFeeConfigUpdates", tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []EVM2EVMMultiOnRampTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []EVM2EVMMultiOnRampTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ApplyTokenTransferFeeConfigUpdates(&_EVM2EVMMultiOnRamp.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactorSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []EVM2EVMMultiOnRampTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []EVM2EVMMultiOnRampTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _EVM2EVMMultiOnRamp.Contract.ApplyTokenTransferFeeConfigUpdates(&_EVM2EVMMultiOnRamp.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) -} - func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampTransactor) ForwardFromRouter(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) { return _EVM2EVMMultiOnRamp.contract.Transact(opts, "forwardFromRouter", destChainSelector, message, feeTokenAmount, originalSender) } @@ -987,8 +823,8 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseConfigSet(log types. return event, nil } -type EVM2EVMMultiOnRampDestChainAddedIterator struct { - Event *EVM2EVMMultiOnRampDestChainAdded +type EVM2EVMMultiOnRampFeePaidIterator struct { + Event *EVM2EVMMultiOnRampFeePaid contract *bind.BoundContract event string @@ -999,7 +835,7 @@ type EVM2EVMMultiOnRampDestChainAddedIterator struct { fail error } -func (it *EVM2EVMMultiOnRampDestChainAddedIterator) Next() bool { +func (it *EVM2EVMMultiOnRampFeePaidIterator) Next() bool { if it.fail != nil { return false @@ -1008,7 +844,7 @@ func (it *EVM2EVMMultiOnRampDestChainAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampDestChainAdded) + it.Event = new(EVM2EVMMultiOnRampFeePaid) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1023,7 +859,7 @@ func (it *EVM2EVMMultiOnRampDestChainAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampDestChainAdded) + it.Event = new(EVM2EVMMultiOnRampFeePaid) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1038,43 +874,43 @@ func (it *EVM2EVMMultiOnRampDestChainAddedIterator) Next() bool { } } -func (it *EVM2EVMMultiOnRampDestChainAddedIterator) Error() error { +func (it *EVM2EVMMultiOnRampFeePaidIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOnRampDestChainAddedIterator) Close() error { +func (it *EVM2EVMMultiOnRampFeePaidIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOnRampDestChainAdded struct { - DestChainSelector uint64 - DestChainConfig EVM2EVMMultiOnRampDestChainConfig - Raw types.Log +type EVM2EVMMultiOnRampFeePaid struct { + FeeToken common.Address + FeeValueJuels *big.Int + Raw types.Log } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*EVM2EVMMultiOnRampDestChainAddedIterator, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterFeePaid(opts *bind.FilterOpts, feeToken []common.Address) (*EVM2EVMMultiOnRampFeePaidIterator, error) { - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "DestChainAdded", destChainSelectorRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "FeePaid", feeTokenRule) if err != nil { return nil, err } - return &EVM2EVMMultiOnRampDestChainAddedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "DestChainAdded", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOnRampFeePaidIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "FeePaid", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeePaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeePaid, feeToken []common.Address) (event.Subscription, error) { - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "DestChainAdded", destChainSelectorRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "FeePaid", feeTokenRule) if err != nil { return nil, err } @@ -1084,8 +920,8 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchDestChainAdded(opts select { case log := <-logs: - event := new(EVM2EVMMultiOnRampDestChainAdded) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "DestChainAdded", log); err != nil { + event := new(EVM2EVMMultiOnRampFeePaid) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeePaid", log); err != nil { return err } event.Raw = log @@ -1106,17 +942,17 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchDestChainAdded(opts }), nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseDestChainAdded(log types.Log) (*EVM2EVMMultiOnRampDestChainAdded, error) { - event := new(EVM2EVMMultiOnRampDestChainAdded) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "DestChainAdded", log); err != nil { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseFeePaid(log types.Log) (*EVM2EVMMultiOnRampFeePaid, error) { + event := new(EVM2EVMMultiOnRampFeePaid) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeePaid", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator struct { - Event *EVM2EVMMultiOnRampDestChainDynamicConfigUpdated +type EVM2EVMMultiOnRampFeeTokenWithdrawnIterator struct { + Event *EVM2EVMMultiOnRampFeeTokenWithdrawn contract *bind.BoundContract event string @@ -1127,7 +963,7 @@ type EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator struct { fail error } -func (it *EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator) Next() bool { +func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Next() bool { if it.fail != nil { return false @@ -1136,7 +972,7 @@ func (it *EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampDestChainDynamicConfigUpdated) + it.Event = new(EVM2EVMMultiOnRampFeeTokenWithdrawn) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1151,7 +987,7 @@ func (it *EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampDestChainDynamicConfigUpdated) + it.Event = new(EVM2EVMMultiOnRampFeeTokenWithdrawn) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1166,43 +1002,52 @@ func (it *EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator) Next() bool { } } -func (it *EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator) Error() error { +func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator) Close() error { +func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOnRampDestChainDynamicConfigUpdated struct { - DestChainSelector uint64 - DynamicConfig EVM2EVMMultiOnRampDestChainDynamicConfig - Raw types.Log +type EVM2EVMMultiOnRampFeeTokenWithdrawn struct { + FeeAggregator common.Address + FeeToken common.Address + Amount *big.Int + Raw types.Log } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterDestChainDynamicConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterFeeTokenWithdrawn(opts *bind.FilterOpts, feeAggregator []common.Address, feeToken []common.Address) (*EVM2EVMMultiOnRampFeeTokenWithdrawnIterator, error) { - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + var feeAggregatorRule []interface{} + for _, feeAggregatorItem := range feeAggregator { + feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) + } + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "DestChainDynamicConfigUpdated", destChainSelectorRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) if err != nil { return nil, err } - return &EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "DestChainDynamicConfigUpdated", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOnRampFeeTokenWithdrawnIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "FeeTokenWithdrawn", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchDestChainDynamicConfigUpdated(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampDestChainDynamicConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeeTokenWithdrawn(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeeTokenWithdrawn, feeAggregator []common.Address, feeToken []common.Address) (event.Subscription, error) { - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + var feeAggregatorRule []interface{} + for _, feeAggregatorItem := range feeAggregator { + feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) + } + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "DestChainDynamicConfigUpdated", destChainSelectorRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) if err != nil { return nil, err } @@ -1212,8 +1057,8 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchDestChainDynamicConf select { case log := <-logs: - event := new(EVM2EVMMultiOnRampDestChainDynamicConfigUpdated) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "DestChainDynamicConfigUpdated", log); err != nil { + event := new(EVM2EVMMultiOnRampFeeTokenWithdrawn) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", log); err != nil { return err } event.Raw = log @@ -1234,17 +1079,17 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchDestChainDynamicConf }), nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseDestChainDynamicConfigUpdated(log types.Log) (*EVM2EVMMultiOnRampDestChainDynamicConfigUpdated, error) { - event := new(EVM2EVMMultiOnRampDestChainDynamicConfigUpdated) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "DestChainDynamicConfigUpdated", log); err != nil { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseFeeTokenWithdrawn(log types.Log) (*EVM2EVMMultiOnRampFeeTokenWithdrawn, error) { + event := new(EVM2EVMMultiOnRampFeeTokenWithdrawn) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOnRampFeePaidIterator struct { - Event *EVM2EVMMultiOnRampFeePaid +type EVM2EVMMultiOnRampOwnershipTransferRequestedIterator struct { + Event *EVM2EVMMultiOnRampOwnershipTransferRequested contract *bind.BoundContract event string @@ -1255,7 +1100,7 @@ type EVM2EVMMultiOnRampFeePaidIterator struct { fail error } -func (it *EVM2EVMMultiOnRampFeePaidIterator) Next() bool { +func (it *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -1264,7 +1109,7 @@ func (it *EVM2EVMMultiOnRampFeePaidIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampFeePaid) + it.Event = new(EVM2EVMMultiOnRampOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1279,7 +1124,7 @@ func (it *EVM2EVMMultiOnRampFeePaidIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampFeePaid) + it.Event = new(EVM2EVMMultiOnRampOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1294,43 +1139,51 @@ func (it *EVM2EVMMultiOnRampFeePaidIterator) Next() bool { } } -func (it *EVM2EVMMultiOnRampFeePaidIterator) Error() error { +func (it *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOnRampFeePaidIterator) Close() error { +func (it *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOnRampFeePaid struct { - FeeToken common.Address - FeeValueJuels *big.Int - Raw types.Log +type EVM2EVMMultiOnRampOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterFeePaid(opts *bind.FilterOpts, feeToken []common.Address) (*EVM2EVMMultiOnRampFeePaidIterator, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferRequestedIterator, error) { - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "FeePaid", feeTokenRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &EVM2EVMMultiOnRampFeePaidIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "FeePaid", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOnRampOwnershipTransferRequestedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeePaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeePaid, feeToken []common.Address) (event.Subscription, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "FeePaid", feeTokenRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -1340,8 +1193,8 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeePaid(opts *bind.W select { case log := <-logs: - event := new(EVM2EVMMultiOnRampFeePaid) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeePaid", log); err != nil { + event := new(EVM2EVMMultiOnRampOwnershipTransferRequested) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -1362,17 +1215,17 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeePaid(opts *bind.W }), nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseFeePaid(log types.Log) (*EVM2EVMMultiOnRampFeePaid, error) { - event := new(EVM2EVMMultiOnRampFeePaid) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeePaid", log); err != nil { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferRequested, error) { + event := new(EVM2EVMMultiOnRampOwnershipTransferRequested) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOnRampFeeTokenWithdrawnIterator struct { - Event *EVM2EVMMultiOnRampFeeTokenWithdrawn +type EVM2EVMMultiOnRampOwnershipTransferredIterator struct { + Event *EVM2EVMMultiOnRampOwnershipTransferred contract *bind.BoundContract event string @@ -1383,7 +1236,7 @@ type EVM2EVMMultiOnRampFeeTokenWithdrawnIterator struct { fail error } -func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Next() bool { +func (it *EVM2EVMMultiOnRampOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -1392,7 +1245,7 @@ func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampFeeTokenWithdrawn) + it.Event = new(EVM2EVMMultiOnRampOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1407,7 +1260,7 @@ func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampFeeTokenWithdrawn) + it.Event = new(EVM2EVMMultiOnRampOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1422,725 +1275,51 @@ func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Next() bool { } } -func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Error() error { +func (it *EVM2EVMMultiOnRampOwnershipTransferredIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOnRampFeeTokenWithdrawnIterator) Close() error { +func (it *EVM2EVMMultiOnRampOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOnRampFeeTokenWithdrawn struct { - FeeAggregator common.Address - FeeToken common.Address - Amount *big.Int - Raw types.Log +type EVM2EVMMultiOnRampOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterFeeTokenWithdrawn(opts *bind.FilterOpts, feeAggregator []common.Address, feeToken []common.Address) (*EVM2EVMMultiOnRampFeeTokenWithdrawnIterator, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferredIterator, error) { - var feeAggregatorRule []interface{} - for _, feeAggregatorItem := range feeAggregator { - feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) } - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampFeeTokenWithdrawnIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "FeeTokenWithdrawn", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchFeeTokenWithdrawn(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeeTokenWithdrawn, feeAggregator []common.Address, feeToken []common.Address) (event.Subscription, error) { - - var feeAggregatorRule []interface{} - for _, feeAggregatorItem := range feeAggregator { - feeAggregatorRule = append(feeAggregatorRule, feeAggregatorItem) - } - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "FeeTokenWithdrawn", feeAggregatorRule, feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampFeeTokenWithdrawn) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseFeeTokenWithdrawn(log types.Log) (*EVM2EVMMultiOnRampFeeTokenWithdrawn, error) { - event := new(EVM2EVMMultiOnRampFeeTokenWithdrawn) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "FeeTokenWithdrawn", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampOwnershipTransferRequestedIterator struct { - Event *EVM2EVMMultiOnRampOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampOwnershipTransferRequested) - 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(EVM2EVMMultiOnRampOwnershipTransferRequested) - 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 *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferRequestedIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampOwnershipTransferRequestedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferRequested, error) { - event := new(EVM2EVMMultiOnRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampOwnershipTransferredIterator struct { - Event *EVM2EVMMultiOnRampOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampOwnershipTransferred) - 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(EVM2EVMMultiOnRampOwnershipTransferred) - 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 *EVM2EVMMultiOnRampOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOnRampOwnershipTransferredIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampOwnershipTransferredIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampOwnershipTransferred) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferred", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferred, error) { - event := new(EVM2EVMMultiOnRampOwnershipTransferred) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdatedIterator struct { - Event *EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated) - 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(EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated) - 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 *EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdatedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated struct { - Token common.Address - PremiumMultiplierWeiPerEth uint64 - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdatedIterator, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdatedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "PremiumMultiplierWeiPerEthUpdated", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { - - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated, error) { - event := new(EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator struct { - Event *EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted) - 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(EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted) - 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 *EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted struct { - DestChainSelector uint64 - Token common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "TokenTransferFeeConfigDeleted", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", 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 (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseTokenTransferFeeConfigDeleted(log types.Log) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, error) { - event := new(EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOnRampTokenTransferFeeConfigUpdatedIterator struct { - Event *EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOnRampTokenTransferFeeConfigUpdatedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated) - 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(EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated) - 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 *EVM2EVMMultiOnRampTokenTransferFeeConfigUpdatedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOnRampTokenTransferFeeConfigUpdatedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated struct { - DestChainSelector uint64 - Token common.Address - TokenTransferFeeConfig EVM2EVMMultiOnRampTokenTransferFeeConfig - Raw types.Log -} - -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigUpdatedIterator, error) { - - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) - } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) - } - - logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &EVM2EVMMultiOnRampTokenTransferFeeConfigUpdatedIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "TokenTransferFeeConfigUpdated", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOnRampOwnershipTransferredIterator{contract: _EVM2EVMMultiOnRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - var destChainSelectorRule []interface{} - for _, destChainSelectorItem := range destChainSelector { - destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) } - var tokenRule []interface{} - for _, tokenItem := range token { - tokenRule = append(tokenRule, tokenItem) + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) } - logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + logs, sub, err := _EVM2EVMMultiOnRamp.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -2150,8 +1329,8 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchTokenTransferFeeConf select { case log := <-logs: - event := new(EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { + event := new(EVM2EVMMultiOnRampOwnershipTransferred) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -2172,9 +1351,9 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) WatchTokenTransferFeeConf }), nil } -func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseTokenTransferFeeConfigUpdated(log types.Log) (*EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated, error) { - event := new(EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated) - if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { +func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferred, error) { + event := new(EVM2EVMMultiOnRampOwnershipTransferred) + if err := _EVM2EVMMultiOnRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log @@ -2189,10 +1368,6 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRamp) ParseLog(log types.Log) (generate return _EVM2EVMMultiOnRamp.ParseCCIPSendRequested(log) case _EVM2EVMMultiOnRamp.abi.Events["ConfigSet"].ID: return _EVM2EVMMultiOnRamp.ParseConfigSet(log) - case _EVM2EVMMultiOnRamp.abi.Events["DestChainAdded"].ID: - return _EVM2EVMMultiOnRamp.ParseDestChainAdded(log) - case _EVM2EVMMultiOnRamp.abi.Events["DestChainDynamicConfigUpdated"].ID: - return _EVM2EVMMultiOnRamp.ParseDestChainDynamicConfigUpdated(log) case _EVM2EVMMultiOnRamp.abi.Events["FeePaid"].ID: return _EVM2EVMMultiOnRamp.ParseFeePaid(log) case _EVM2EVMMultiOnRamp.abi.Events["FeeTokenWithdrawn"].ID: @@ -2201,12 +1376,6 @@ func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRamp) ParseLog(log types.Log) (generate return _EVM2EVMMultiOnRamp.ParseOwnershipTransferRequested(log) case _EVM2EVMMultiOnRamp.abi.Events["OwnershipTransferred"].ID: return _EVM2EVMMultiOnRamp.ParseOwnershipTransferred(log) - case _EVM2EVMMultiOnRamp.abi.Events["PremiumMultiplierWeiPerEthUpdated"].ID: - return _EVM2EVMMultiOnRamp.ParsePremiumMultiplierWeiPerEthUpdated(log) - case _EVM2EVMMultiOnRamp.abi.Events["TokenTransferFeeConfigDeleted"].ID: - return _EVM2EVMMultiOnRamp.ParseTokenTransferFeeConfigDeleted(log) - case _EVM2EVMMultiOnRamp.abi.Events["TokenTransferFeeConfigUpdated"].ID: - return _EVM2EVMMultiOnRamp.ParseTokenTransferFeeConfigUpdated(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) @@ -2222,15 +1391,7 @@ func (EVM2EVMMultiOnRampCCIPSendRequested) Topic() common.Hash { } func (EVM2EVMMultiOnRampConfigSet) Topic() common.Hash { - return common.HexToHash("0x4012fe74115805c44a121d8f9edc3d234df8f05f53b52864b8e5e8a30384b8aa") -} - -func (EVM2EVMMultiOnRampDestChainAdded) Topic() common.Hash { - return common.HexToHash("0x26f8c55bd3f591fd6042c98ad4d707257cd565dc47609bfa3ba517400d057044") -} - -func (EVM2EVMMultiOnRampDestChainDynamicConfigUpdated) Topic() common.Hash { - return common.HexToHash("0xd42d3a670a4f1ab5d8703efa22bb17041446365cfcfa33980ced685a080cf7cb") + return common.HexToHash("0x23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32") } func (EVM2EVMMultiOnRampFeePaid) Topic() common.Hash { @@ -2249,25 +1410,11 @@ func (EVM2EVMMultiOnRampOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated) Topic() common.Hash { - return common.HexToHash("0xbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d") -} - -func (EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted) Topic() common.Hash { - return common.HexToHash("0x4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b") -} - -func (EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated) Topic() common.Hash { - return common.HexToHash("0x94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5") -} - func (_EVM2EVMMultiOnRamp *EVM2EVMMultiOnRamp) Address() common.Address { return _EVM2EVMMultiOnRamp.address } type EVM2EVMMultiOnRampInterface interface { - GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (EVM2EVMMultiOnRampDestChainConfig, error) - GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampDynamicConfig, error) GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) @@ -2276,26 +1423,16 @@ type EVM2EVMMultiOnRampInterface interface { GetPoolBySourceToken(opts *bind.CallOpts, arg0 uint64, sourceToken common.Address) (common.Address, error) - GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) - GetStaticConfig(opts *bind.CallOpts) (EVM2EVMMultiOnRampStaticConfig, error) GetSupportedTokens(opts *bind.CallOpts, arg0 uint64) ([]common.Address, error) - GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (EVM2EVMMultiOnRampTokenTransferFeeConfig, error) - Owner(opts *bind.CallOpts) (common.Address, error) TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []EVM2EVMMultiOnRampDestChainConfigArgs) (*types.Transaction, error) - - ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) - - ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []EVM2EVMMultiOnRampTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []EVM2EVMMultiOnRampTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) - ForwardFromRouter(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig EVM2EVMMultiOnRampDynamicConfig) (*types.Transaction, error) @@ -2322,18 +1459,6 @@ type EVM2EVMMultiOnRampInterface interface { ParseConfigSet(log types.Log) (*EVM2EVMMultiOnRampConfigSet, error) - FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*EVM2EVMMultiOnRampDestChainAddedIterator, error) - - WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampDestChainAdded, destChainSelector []uint64) (event.Subscription, error) - - ParseDestChainAdded(log types.Log) (*EVM2EVMMultiOnRampDestChainAdded, error) - - FilterDestChainDynamicConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*EVM2EVMMultiOnRampDestChainDynamicConfigUpdatedIterator, error) - - WatchDestChainDynamicConfigUpdated(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampDestChainDynamicConfigUpdated, destChainSelector []uint64) (event.Subscription, error) - - ParseDestChainDynamicConfigUpdated(log types.Log) (*EVM2EVMMultiOnRampDestChainDynamicConfigUpdated, error) - FilterFeePaid(opts *bind.FilterOpts, feeToken []common.Address) (*EVM2EVMMultiOnRampFeePaidIterator, error) WatchFeePaid(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampFeePaid, feeToken []common.Address) (event.Subscription, error) @@ -2358,24 +1483,6 @@ type EVM2EVMMultiOnRampInterface interface { ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOnRampOwnershipTransferred, error) - FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdatedIterator, error) - - WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) - - ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthUpdated, error) - - FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeletedIterator, error) - - WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) - - ParseTokenTransferFeeConfigDeleted(log types.Log) (*EVM2EVMMultiOnRampTokenTransferFeeConfigDeleted, error) - - FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*EVM2EVMMultiOnRampTokenTransferFeeConfigUpdatedIterator, error) - - WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) - - ParseTokenTransferFeeConfigUpdated(log types.Log) (*EVM2EVMMultiOnRampTokenTransferFeeConfigUpdated, error) - ParseLog(log types.Log) (generated.AbigenLog, error) Address() common.Address diff --git a/core/gethwrappers/ccip/generated/price_registry/price_registry.go b/core/gethwrappers/ccip/generated/price_registry/price_registry.go index 5b18229872..19f1bd4a19 100644 --- a/core/gethwrappers/ccip/generated/price_registry/price_registry.go +++ b/core/gethwrappers/ccip/generated/price_registry/price_registry.go @@ -35,6 +35,19 @@ type AuthorizedCallersAuthorizedCallerArgs struct { RemovedCallers []common.Address } +type ClientEVM2AnyMessage struct { + Receiver []byte + Data []byte + TokenAmounts []ClientEVMTokenAmount + FeeToken common.Address + ExtraArgs []byte +} + +type ClientEVMTokenAmount struct { + Token common.Address + Amount *big.Int +} + type IPriceRegistryTokenPriceFeedConfig struct { DataFeedAddress common.Address TokenDecimals uint8 @@ -50,6 +63,13 @@ type InternalPriceUpdates struct { GasPriceUpdates []InternalGasPriceUpdate } +type InternalRampTokenAmount struct { + SourcePoolAddress []byte + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int +} + type InternalTimestampedPackedUint224 struct { Value *big.Int Timestamp uint32 @@ -60,21 +80,81 @@ type InternalTokenPriceUpdate struct { UsdPerToken *big.Int } +type PriceRegistryDestChainConfig struct { + IsEnabled bool + MaxNumberOfTokensPerMsg uint16 + MaxDataBytes uint32 + MaxPerMsgGasLimit uint32 + DestGasOverhead uint32 + DestGasPerPayloadByte uint16 + DestDataAvailabilityOverheadGas uint32 + DestGasPerDataAvailabilityByte uint16 + DestDataAvailabilityMultiplierBps uint16 + DefaultTokenFeeUSDCents uint16 + DefaultTokenDestGasOverhead uint32 + DefaultTokenDestBytesOverhead uint32 + DefaultTxGasLimit uint32 + GasMultiplierWeiPerEth uint64 + NetworkFeeUSDCents uint32 + EnforceOutOfOrder bool + ChainFamilySelector [4]byte +} + +type PriceRegistryDestChainConfigArgs struct { + DestChainSelector uint64 + DestChainConfig PriceRegistryDestChainConfig +} + +type PriceRegistryPremiumMultiplierWeiPerEthArgs struct { + Token common.Address + PremiumMultiplierWeiPerEth uint64 +} + +type PriceRegistryStaticConfig struct { + MaxFeeJuelsPerMsg *big.Int + LinkToken common.Address + StalenessThreshold uint32 +} + type PriceRegistryTokenPriceFeedUpdate struct { SourceToken common.Address FeedConfig IPriceRegistryTokenPriceFeedConfig } +type PriceRegistryTokenTransferFeeConfig struct { + MinFeeUSDCents uint32 + MaxFeeUSDCents uint32 + DeciBps uint16 + DestGasOverhead uint32 + DestBytesOverhead uint32 + IsEnabled bool +} + +type PriceRegistryTokenTransferFeeConfigArgs struct { + DestChainSelector uint64 + TokenTransferFeeConfigs []PriceRegistryTokenTransferFeeConfigSingleTokenArgs +} + +type PriceRegistryTokenTransferFeeConfigRemoveArgs struct { + DestChainSelector uint64 + Token common.Address +} + +type PriceRegistryTokenTransferFeeConfigSingleTokenArgs struct { + Token common.Address + TokenTransferFeeConfig PriceRegistryTokenTransferFeeConfig +} + var PriceRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStalenessThreshold\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"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\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStalenessThreshold\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"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\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162002b9938038062002b99833981016040819052620000349162000828565b8333806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000151565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620001fc565b506040805160008152602081019091526200010b9084906200034b565b620001168162000493565b8163ffffffff166000036200013e57604051631151410960e11b815260040160405180910390fd5b5063ffffffff1660805250620009f79050565b336001600160a01b03821603620001ab5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b81518110156200028c576000828281518110620002255762000225620009a9565b602090810291909101015190506200023f60028262000564565b1562000282576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b5060010162000204565b50815160005b815181101562000345576000828281518110620002b357620002b3620009a9565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002f1576040516342bcdf7f60e11b815260040160405180910390fd5b620002fe60028262000584565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000292565b50505050565b60005b8251811015620003ec576200038a838281518110620003715762000371620009a9565b602002602001015160096200058460201b90919060201c565b15620003e357828181518110620003a557620003a5620009a9565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016200034e565b5060005b81518110156200048e576200042c828281518110620004135762000413620009a9565b602002602001015160096200056460201b90919060201c565b156200048557818181518110620004475762000447620009a9565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620003f0565b505050565b60005b815181101562000560576000828281518110620004b757620004b7620009a9565b6020908102919091018101518051818301516001600160a01b0380831660008181526006875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905062000496565b5050565b60006200057b836001600160a01b0384166200059b565b90505b92915050565b60006200057b836001600160a01b0384166200069f565b6000818152600183016020526040812054801562000694576000620005c2600183620009bf565b8554909150600090620005d890600190620009bf565b905081811462000644576000866000018281548110620005fc57620005fc620009a9565b9060005260206000200154905080876000018481548110620006225762000622620009a9565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620006585762000658620009e1565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506200057e565b60009150506200057e565b6000818152600183016020526040812054620006e8575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200057e565b5060006200057e565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200072c576200072c620006f1565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200075d576200075d620006f1565b604052919050565b60006001600160401b03821115620007815762000781620006f1565b5060051b60200190565b80516001600160a01b0381168114620007a357600080fd5b919050565b600082601f830112620007ba57600080fd5b81516020620007d3620007cd8362000765565b62000732565b8083825260208201915060208460051b870101935086841115620007f657600080fd5b602086015b848110156200081d576200080f816200078b565b8352918301918301620007fb565b509695505050505050565b600080600080608085870312156200083f57600080fd5b84516001600160401b03808211156200085757600080fd5b6200086588838901620007a8565b95506020915081870151818111156200087d57600080fd5b6200088b89828a01620007a8565b95505060408088015163ffffffff81168114620008a757600080fd5b8095505060608089015183811115620008bf57600080fd5b89019250601f83018a13620008d357600080fd5b8251620008e4620007cd8262000765565b81815260609091028401850190858101908c8311156200090357600080fd5b948601945b828610156200099857858d0384811215620009235760008081fd5b6200092d62000707565b62000938886200078b565b815286601f19830112156200094d5760008081fd5b6200095762000707565b9150620009668989016200078b565b82528688015160ff811681146200097d5760008081fd5b828a0152808901919091528252948301949086019062000908565b999c989b5096995050505050505050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200057e57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805161217862000a216000396000818161034901528181610bee0152610c5701526121786000f3fe608060405234801561001057600080fd5b50600436106101355760003560e01c80637afac322116100b2578063bf78e03f11610081578063d02641a011610066578063d02641a014610428578063f2fde38b1461043b578063ffdb4b371461044e57600080fd5b8063bf78e03f14610373578063cdc73d511461042057600080fd5b80637afac322146102f15780638da5cb5b1461030457806391a2749a1461032c578063a6c94a731461033f57600080fd5b8063407e1086116101095780634ab35b0b116100ee5780634ab35b0b14610206578063514e8cff1461024657806379ba5097146102e957600080fd5b8063407e1086146101d357806345ac924d146101e657600080fd5b806241e5be1461013a578063181f5a77146101605780632451a627146101a95780633937306f146101be575b600080fd5b61014d61014836600461175a565b610496565b6040519081526020015b60405180910390f35b61019c6040518060400160405280601781526020017f5072696365526567697374727920312e362e302d64657600000000000000000081525081565b6040516101579190611796565b6101b1610502565b6040516101579190611803565b6101d16101cc36600461185d565b610513565b005b6101d16101e1366004611972565b6107e7565b6101f96101f4366004611a8b565b6107fb565b6040516101579190611b00565b610219610214366004611b7b565b6108c6565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610157565b6102dc610254366004611bae565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600460209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101579190611bc9565b6101d16108d1565b6101d16102ff366004611c75565b6109d3565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610157565b6101d161033a366004611cd9565b6109e9565b60405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610157565b6103ec610381366004611b7b565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526006825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff169281019290925201610157565b6101b16109fa565b6102dc610436366004611b7b565b610a06565b6101d1610449366004611b7b565b610b09565b61046161045c366004611d6a565b610b1a565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610157565b60006104a182610ca5565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166104c885610ca5565b6104f0907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685611dcc565b6104fa9190611de3565b949350505050565b606061050e6002610d3f565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331461053a5761053a610d4c565b60006105468280611e1e565b9050905060005b818110156106905760006105618480611e1e565b8381811061057157610571611e86565b9050604002018036038101906105879190611ee1565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a9261067f9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a25060010161054d565b5060006106a06020840184611e1e565b9050905060005b818110156107e15760006106be6020860186611e1e565b838181106106ce576106ce611e86565b9050604002018036038101906106e49190611f1e565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600490975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926107d09290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a2506001016106a7565b50505050565b6107ef610d91565b6107f881610e12565b50565b60608160008167ffffffffffffffff81111561081957610819611898565b60405190808252806020026020018201604052801561085e57816020015b60408051808201909152600080825260208201528152602001906001900390816108375790505b50905060005b828110156108bb5761089686868381811061088157610881611e86565b90506020020160208101906104369190611b7b565b8282815181106108a8576108a8611e86565b6020908102919091010152600101610864565b509150505b92915050565b60006108c082610ca5565b60015473ffffffffffffffffffffffffffffffffffffffff163314610957576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6109db610d91565b6109e58282610f10565b5050565b6109f1610d91565b6107f88161105c565b606061050e6009610d3f565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600660209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290610af957505073ffffffffffffffffffffffffffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b02816111e8565b9392505050565b610b11610d91565b6107f88161142b565b67ffffffffffffffff811660009081526004602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203610bd2576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8516600482015260240161094e565b6000816020015163ffffffff1642610bea9190611f41565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115610c8b576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044810182905260640161094e565b610c9486610ca5565b9151919350909150505b9250929050565b600080610cb183610a06565b9050806020015163ffffffff1660001480610ce9575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15610d38576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161094e565b5192915050565b60606000610b0283611520565b610d5760023361157c565b610d8f576040517fd86ad9cf00000000000000000000000000000000000000000000000000000000815233600482015260240161094e565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161094e565b60005b81518110156109e5576000828281518110610e3257610e32611e86565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526006875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050610e15565b60005b8251811015610fb357610f49838281518110610f3157610f31611e86565b602002602001015160096115ab90919063ffffffff16565b15610fab57828181518110610f6057610f60611e86565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101610f13565b5060005b815181101561105757610fed828281518110610fd557610fd5611e86565b602002602001015160096115cd90919063ffffffff16565b1561104f5781818151811061100457611004611e86565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101610fb7565b505050565b602081015160005b81518110156110f757600082828151811061108157611081611e86565b6020026020010151905061109f8160026115cd90919063ffffffff16565b156110ee5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101611064565b50815160005b81518110156107e157600082828151811061111a5761111a611e86565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361118a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111956002826115ab565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016110fd565b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112769190611f6e565b50505091505060008112156112b7576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000819050600085602001518473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561130e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113329190611fbe565b61133c9190611fdb565b905060248160ff16111561137157611355602482611ff4565b61136090600a61212d565b61136a9083611de3565b9150611394565b61137c816024611ff4565b61138790600a61212d565b6113919083611dcc565b91505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156113ea576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff42166020820152949350505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036114aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161094e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60608160000180548060200260200160405190810160405280929190818152602001828054801561157057602002820191906000526020600020905b81548152602001906001019080831161155c575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b02565b6000610b028373ffffffffffffffffffffffffffffffffffffffff84166115ef565b6000610b028373ffffffffffffffffffffffffffffffffffffffff841661163e565b6000818152600183016020526040812054611636575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556108c0565b5060006108c0565b60008181526001830160205260408120548015611727576000611662600183611f41565b855490915060009061167690600190611f41565b90508181146116db57600086600001828154811061169657611696611e86565b90600052602060002001549050808760000184815481106116b9576116b9611e86565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806116ec576116ec61213c565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506108c0565b60009150506108c0565b803573ffffffffffffffffffffffffffffffffffffffff8116811461175557600080fd5b919050565b60008060006060848603121561176f57600080fd5b61177884611731565b92506020840135915061178d60408501611731565b90509250925092565b60006020808352835180602085015260005b818110156117c4578581018301518582016040015282016117a8565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6020808252825182820181905260009190848201906040850190845b8181101561185157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161181f565b50909695505050505050565b60006020828403121561186f57600080fd5b813567ffffffffffffffff81111561188657600080fd5b820160408185031215610b0257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156118ea576118ea611898565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561193757611937611898565b604052919050565b600067ffffffffffffffff82111561195957611959611898565b5060051b60200190565b60ff811681146107f857600080fd5b6000602080838503121561198557600080fd5b823567ffffffffffffffff81111561199c57600080fd5b8301601f810185136119ad57600080fd5b80356119c06119bb8261193f565b6118f0565b818152606091820283018401918482019190888411156119df57600080fd5b938501935b83851015611a7f57848903818112156119fd5760008081fd5b611a056118c7565b611a0e87611731565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215611a425760008081fd5b611a4a6118c7565b9250611a57898901611731565b8352870135611a6581611963565b8289015280880191909152835293840193918501916119e4565b50979650505050505050565b60008060208385031215611a9e57600080fd5b823567ffffffffffffffff80821115611ab657600080fd5b818501915085601f830112611aca57600080fd5b813581811115611ad957600080fd5b8660208260051b8501011115611aee57600080fd5b60209290920196919550909350505050565b602080825282518282018190526000919060409081850190868401855b82811015611b6e57611b5e84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101611b1d565b5091979650505050505050565b600060208284031215611b8d57600080fd5b610b0282611731565b803567ffffffffffffffff8116811461175557600080fd5b600060208284031215611bc057600080fd5b610b0282611b96565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016108c0565b600082601f830112611c1557600080fd5b81356020611c256119bb8361193f565b8083825260208201915060208460051b870101935086841115611c4757600080fd5b602086015b84811015611c6a57611c5d81611731565b8352918301918301611c4c565b509695505050505050565b60008060408385031215611c8857600080fd5b823567ffffffffffffffff80821115611ca057600080fd5b611cac86838701611c04565b93506020850135915080821115611cc257600080fd5b50611ccf85828601611c04565b9150509250929050565b600060208284031215611ceb57600080fd5b813567ffffffffffffffff80821115611d0357600080fd5b9083019060408286031215611d1757600080fd5b611d1f6118c7565b823582811115611d2e57600080fd5b611d3a87828601611c04565b825250602083013582811115611d4f57600080fd5b611d5b87828601611c04565b60208301525095945050505050565b60008060408385031215611d7d57600080fd5b611d8683611731565b9150611d9460208401611b96565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176108c0576108c0611d9d565b600082611e19577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611e5357600080fd5b83018035915067ffffffffffffffff821115611e6e57600080fd5b6020019150600681901b3603821315610c9e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461175557600080fd5b600060408284031215611ef357600080fd5b611efb6118c7565b611f0483611731565b8152611f1260208401611eb5565b60208201529392505050565b600060408284031215611f3057600080fd5b611f386118c7565b611f0483611b96565b818103818111156108c0576108c0611d9d565b805169ffffffffffffffffffff8116811461175557600080fd5b600080600080600060a08688031215611f8657600080fd5b611f8f86611f54565b9450602086015193506040860151925060608601519150611fb260808701611f54565b90509295509295909350565b600060208284031215611fd057600080fd5b8151610b0281611963565b60ff81811683821601908111156108c0576108c0611d9d565b60ff82811682821603908111156108c0576108c0611d9d565b600181815b8085111561206657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561204c5761204c611d9d565b8085161561205957918102915b93841c9390800290612012565b509250929050565b60008261207d575060016108c0565b8161208a575060006108c0565b81600181146120a057600281146120aa576120c6565b60019150506108c0565b60ff8411156120bb576120bb611d9d565b50506001821b6108c0565b5060208310610133831016604e8410600b84101617156120e9575081810a6108c0565b6120f3838361200d565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561212557612125611d9d565b029392505050565b6000610b0260ff84168361206e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"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\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"priceUpdater\",\"type\":\"address\"}],\"name\":\"PriceUpdaterSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"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\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"validatePoolReturnData\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b50604051620069373803806200693783398101604081905262000034916200180a565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a99565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b65565b5050505050505062001ac8565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001929565b60209081029190910101519050620002f560028262000e98565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001929565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000eb8565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001929565b6020026020010151600c62000eb860201b90919060201c565b1562000499578281815181106200045b576200045b62001929565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001929565b6020026020010151600c62000e9860201b90919060201c565b156200053b57818181518110620004fd57620004fd62001929565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001929565b6020908102919091018101518051818301516001600160a01b0380831660008181526006875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001929565b6020026020010151905060008383815181106200065f576200065f62001929565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061018081015163ffffffff16155b80620006ba57506102008101516001600160e01b031916630a04b54b60e21b14155b80620006d15750602081610160015163ffffffff16105b80620006f15750806060015163ffffffff1681610180015163ffffffff16115b156200071c5760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260086020526040812060010154600160a81b900460e01b6001600160e01b03191690036200079c57816001600160401b03167fa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d13577826040516200078e91906200193f565b60405180910390a2620007e0565b816001600160401b03167fa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad9382604051620007d791906200193f565b60405180910390a25b8060086000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101a08201518160010160086101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000abd5762000abd62001929565b6020026020010151600001519050600083838151811062000ae25762000ae262001929565b6020908102919091018101518101516001600160a01b03841660008181526007845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a9c565b60005b825181101562000dd257600083828151811062000b895762000b8962001929565b6020026020010151905060008160000151905060005b82602001515181101562000dc35760008360200151828151811062000bc85762000bc862001929565b602002602001015160200151905060008460200151838151811062000bf15762000bf162001929565b60200260200101516000015190506020826080015163ffffffff16101562000c4a5760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b03841660008181526009602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000db0908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b9f565b50505080600101905062000b68565b5060005b81518110156200054457600082828151811062000df75762000df762001929565b6020026020010151600001519050600083838151811062000e1c5762000e1c62001929565b6020908102919091018101518101516001600160401b03841660008181526009845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000dd6565b600062000eaf836001600160a01b03841662000ecf565b90505b92915050565b600062000eaf836001600160a01b03841662000fd3565b6000818152600183016020526040812054801562000fc857600062000ef660018362001a90565b855490915060009062000f0c9060019062001a90565b905081811462000f7857600086600001828154811062000f305762000f3062001929565b906000526020600020015490508087600001848154811062000f565762000f5662001929565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f8c5762000f8c62001ab2565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000eb2565b600091505062000eb2565b60008181526001830160205260408120546200101c5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000eb2565b50600062000eb2565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b038111828210171562001060576200106062001025565b60405290565b60405160c081016001600160401b038111828210171562001060576200106062001025565b60405161022081016001600160401b038111828210171562001060576200106062001025565b604051601f8201601f191681016001600160401b0381118282101715620010dc57620010dc62001025565b604052919050565b80516001600160a01b0381168114620010fc57600080fd5b919050565b805163ffffffff81168114620010fc57600080fd5b6000606082840312156200112957600080fd5b604051606081016001600160401b03811182821017156200114e576200114e62001025565b604052825190915081906001600160601b03811681146200116e57600080fd5b81526200117e60208401620010e4565b6020820152620011916040840162001101565b60408201525092915050565b60006001600160401b03821115620011b957620011b962001025565b5060051b60200190565b600082601f830112620011d557600080fd5b81516020620011ee620011e8836200119d565b620010b1565b8083825260208201915060208460051b8701019350868411156200121157600080fd5b602086015b8481101562001238576200122a81620010e4565b835291830191830162001216565b509695505050505050565b600082601f8301126200125557600080fd5b8151602062001268620011e8836200119d565b828152606092830285018201928282019190878511156200128857600080fd5b8387015b858110156200131b5780890382811215620012a75760008081fd5b620012b16200103b565b620012bc83620010e4565b8152604080601f1984011215620012d35760008081fd5b620012dd6200103b565b9250620012ec888501620010e4565b835283015160ff81168114620013025760008081fd5b828801528087019190915284529284019281016200128c565b5090979650505050505050565b80516001600160401b0381168114620010fc57600080fd5b805161ffff81168114620010fc57600080fd5b80518015158114620010fc57600080fd5b600082601f8301126200137657600080fd5b8151602062001389620011e8836200119d565b82815260059290921b84018101918181019086841115620013a957600080fd5b8286015b84811015620012385780516001600160401b0380821115620013ce57600080fd5b908801906040601f19838c038101821315620013e957600080fd5b620013f36200103b565b6200140089860162001328565b815282850151848111156200141457600080fd5b8086019550508c603f8601126200142a57600080fd5b8885015193506200143f620011e8856200119d565b84815260e09094028501830193898101908e8611156200145e57600080fd5b958401955b858710156200153757868f0360e08112156200147e57600080fd5b620014886200103b565b6200149389620010e4565b815260c08683011215620014a657600080fd5b620014b062001066565b9150620014bf8d8a0162001101565b8252620014ce878a0162001101565b8d830152620014e060608a0162001340565b87830152620014f260808a0162001101565b60608301526200150560a08a0162001101565b60808301526200151860c08a0162001353565b60a0830152808d0191909152825260e09690960195908a019062001463565b828b015250875250505092840192508301620013ad565b600082601f8301126200156057600080fd5b8151602062001573620011e8836200119d565b82815260069290921b840181019181810190868411156200159357600080fd5b8286015b84811015620012385760408189031215620015b25760008081fd5b620015bc6200103b565b620015c782620010e4565b8152620015d685830162001328565b8186015283529183019160400162001597565b80516001600160e01b031981168114620010fc57600080fd5b600082601f8301126200161457600080fd5b8151602062001627620011e8836200119d565b82815261024092830285018201928282019190878511156200164857600080fd5b8387015b858110156200131b5780890382811215620016675760008081fd5b620016716200103b565b6200167c8362001328565b815261022080601f1984011215620016945760008081fd5b6200169e6200108b565b9250620016ad88850162001353565b83526040620016be81860162001340565b898501526060620016d181870162001101565b8286015260809150620016e682870162001101565b9085015260a0620016f986820162001101565b8286015260c091506200170e82870162001340565b9085015260e06200172186820162001101565b8286015261010091506200173782870162001340565b908501526101206200174b86820162001340565b8286015261014091506200176182870162001340565b908501526101606200177586820162001101565b8286015261018091506200178b82870162001101565b908501526101a06200179f86820162001101565b828601526101c09150620017b582870162001328565b908501526101e0620017c986820162001101565b828601526102009150620017df82870162001353565b90850152620017f0858301620015e9565b90840152508087019190915284529284019281016200164c565b6000806000806000806000610120888a0312156200182757600080fd5b62001833898962001116565b60608901519097506001600160401b03808211156200185157600080fd5b6200185f8b838c01620011c3565b975060808a01519150808211156200187657600080fd5b620018848b838c01620011c3565b965060a08a01519150808211156200189b57600080fd5b620018a98b838c0162001243565b955060c08a0151915080821115620018c057600080fd5b620018ce8b838c0162001364565b945060e08a0151915080821115620018e557600080fd5b620018f38b838c016200154e565b93506101008a01519150808211156200190b57600080fd5b506200191a8a828b0162001602565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b8151151581526102208101602083015162001960602084018261ffff169052565b50604083015162001979604084018263ffffffff169052565b50606083015162001992606084018263ffffffff169052565b506080830151620019ab608084018263ffffffff169052565b5060a0830151620019c260a084018261ffff169052565b5060c0830151620019db60c084018263ffffffff169052565b5060e0830151620019f260e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501518216908401526101a0808501516001600160401b0316908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000eb257634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051614e1562001b22600039600081816102d901528181611ad30152611b3c01526000818161029d0152818161104e01526110ae015260008181610269015281816110d701526111470152614e156000f3fe608060405234801561001057600080fd5b50600436106101b85760003560e01c80637afac322116100f9578063cc88924c11610097578063d8694ccd11610071578063d8694ccd14610a5c578063f2fde38b14610a6f578063f700042a14610a82578063ffdb4b3714610a9557600080fd5b8063cc88924c14610a2e578063cdc73d5114610a41578063d02641a014610a4957600080fd5b806391a2749a116100d357806391a2749a14610939578063a69c64c01461094c578063bf78e03f1461095f578063c4276bfc14610a0c57600080fd5b80637afac3221461078e57806382b49eb0146107a15780638da5cb5b1461091157600080fd5b8063407e108611610166578063514e8cff11610140578063514e8cff146104385780636def4ce7146104db578063770e2dc41461077357806379ba50971461078657600080fd5b8063407e1086146103c557806345ac924d146103d85780634ab35b0b146103f857600080fd5b8063181f5a7711610197578063181f5a77146103525780632451a6271461039b5780633937306f146103b057600080fd5b806241e5be146101bd578063061877e3146101e357806306285c691461023c575b600080fd5b6101d06101cb366004613802565b610add565b6040519081526020015b60405180910390f35b6102236101f136600461383e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526007602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101da565b610306604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101da565b61038e6040518060400160405280601781526020017f5072696365526567697374727920312e362e302d64657600000000000000000081525081565b6040516101da91906138bd565b6103a3610b4b565b6040516101da91906138d0565b6103c36103be36600461392a565b610b5c565b005b6103c36103d3366004613a86565b610e11565b6103eb6103e6366004613be4565b610e25565b6040516101da9190613c26565b61040b61040636600461383e565b610ef0565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101da565b6104ce610446366004613cb9565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600460209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101da9190613cd4565b6107666104e9366004613cb9565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260086020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b010000000000000000000000000000000000000000000000000000009092048616610140840152600190930154808616610160840152640100000000810486166101808401526801000000000000000081049096166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516101da9190613d0f565b6103c3610781366004613f4c565b610efb565b6103c3610f11565b6103c361079c366004614266565b611013565b6108b16107af3660046142ca565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff91909116600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101da9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101da565b6103c36109473660046142f4565b611025565b6103c361095a366004614385565b611036565b6109d861096d36600461383e565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526006825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101da565b610a1f610a1a36600461444a565b611047565b6040516101da939291906144e5565b6103c3610a3c36600461450f565b611245565b6103a361141b565b6104ce610a5736600461383e565b611427565b6101d0610a6a3660046145aa565b611523565b6103c3610a7d36600461383e565b6119dd565b6103c3610a9036600461462f565b6119ee565b610aa8610aa336600461484f565b6119ff565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101da565b6000610ae882611b8a565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b0f85611b8a565b610b37907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856148a8565b610b4191906148bf565b90505b9392505050565b6060610b576002611c24565b905090565b610b64611c31565b6000610b7082806148fa565b9050905060005b81811015610cba576000610b8b84806148fa565b83818110610b9b57610b9b614962565b905060400201803603810190610bb191906149bd565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610ca99290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610b77565b506000610cca60208401846148fa565b9050905060005b81811015610e0b576000610ce860208601866148fa565b83818110610cf857610cf8614962565b905060400201803603810190610d0e91906149fa565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600490975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610dfa9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610cd1565b50505050565b610e19611c76565b610e2281611cf7565b50565b60608160008167ffffffffffffffff811115610e4357610e43613965565b604051908082528060200260200182016040528015610e8857816020015b6040805180820190915260008082526020820152815260200190600190039081610e615790505b50905060005b82811015610ee557610ec0868683818110610eab57610eab614962565b9050602002016020810190610a57919061383e565b828281518110610ed257610ed2614962565b6020908102919091010152600101610e8e565b509150505b92915050565b6000610eea82611b8a565b610f03611c76565b610f0d8282611df5565b5050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610f97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61101b611c76565b610f0d8282612201565b61102d611c76565b610e2281612348565b61103e611c76565b610e22816124d4565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036110a7578592506110d5565b6110d287877f0000000000000000000000000000000000000000000000000000000000000000610add565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611174576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610f8e565b67ffffffffffffffff8816600090815260086020526040812060010154640100000000900463ffffffff16906111ab8787846125be565b9050806020015193508484611232836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b67ffffffffffffffff85166000908152600860205260408120600101547501000000000000000000000000000000000000000000900460e01b905b8481101561141257600084848381811061129c5761129c614962565b6112b2926020604090920201908101915061383e565b905060008787848181106112c8576112c8614962565b90506020028101906112da9190614a1d565b6112e8906040810190614a5b565b91505060208111156113985767ffffffffffffffff8916600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115611398576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610f8e565b611408848989868181106113ae576113ae614962565b90506020028101906113c09190614a1d565b6113ce906020810190614a5b565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061276792505050565b5050600101611280565b50505050505050565b6060610b57600c611c24565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600660209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff16908201529061151a57505073ffffffffffffffffffffffffffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b44816127b9565b67ffffffffffffffff8083166000908152600860209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b010000000000000000000000000000000000000000000000000000009093048616610140850152600190940154808616610160850152640100000000810486166101808501526801000000000000000081049098166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611759576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610f8e565b600061176860408501856148fa565b91506117c490508261177d6020870187614a5b565b90508361178a8880614a5b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506129fc92505050565b60006007816117d9608088016060890161383e565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff169150806118286118226080890160608a0161383e565b896119ff565b909250905060008080861561186e57611862888c61184c60808e0160608f0161383e565b888e806040019061185d91906148fa565b612aa6565b9194509250905061188e565b6101c088015161188b9063ffffffff16662386f26fc100006148a8565b92505b61010088015160009061ffff16156118d2576118cf896dffffffffffffffffffffffffffff607088901c166118c660208f018f614a5b565b90508b86612d84565b90505b6101a089015160009067ffffffffffffffff166118fb6118f560808f018f614a5b565b8d612e33565b600001518563ffffffff168c60a0015161ffff168f806020019061191f9190614a5b565b61192a9291506148a8565b8d6080015163ffffffff1661193f9190614ac0565b6119499190614ac0565b6119539190614ac0565b61196d906dffffffffffffffffffffffffffff89166148a8565b61197791906148a8565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff871682826119ae67ffffffffffffffff8c16896148a8565b6119b89190614ac0565b6119c29190614ac0565b6119cc91906148bf565b9d9c50505050505050505050505050565b6119e5611c76565b610e2281612ef4565b6119f6611c76565b610e2281612fe9565b67ffffffffffffffff811660009081526004602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203611ab7576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610f8e565b6000816020015163ffffffff1642611acf9190614ad3565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115611b70576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610f8e565b611b7986611b8a565b9151919350909150505b9250929050565b600080611b9683611427565b9050806020015163ffffffff1660001480611bce575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15611c1d576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610f8e565b5192915050565b60606000610b44836134d1565b611c3c60023361352d565b611c74576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610f8e565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314611c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610f8e565b60005b8151811015610f0d576000828281518110611d1757611d17614962565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526006875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050611cfa565b60005b8251811015612118576000838281518110611e1557611e15614962565b6020026020010151905060008160000151905060005b82602001515181101561210a57600083602001518281518110611e5057611e50614962565b6020026020010151602001519050600084602001518381518110611e7657611e76614962565b60200260200101516000015190506020826080015163ffffffff161015611ef35760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610f8e565b67ffffffffffffffff8416600081815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906120f8908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101611e2b565b505050806001019050611df8565b5060005b81518110156121fc57600082828151811061213957612139614962565b6020026020010151600001519050600083838151811061215b5761215b614962565b60209081029190910181015181015167ffffffffffffffff8416600081815260098452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010161211c565b505050565b60005b82518110156122a45761223a83828151811061222257612222614962565b6020026020010151600c61355c90919063ffffffff16565b1561229c5782818151811061225157612251614962565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612204565b5060005b81518110156121fc576122de8282815181106122c6576122c6614962565b6020026020010151600c61357e90919063ffffffff16565b15612340578181815181106122f5576122f5614962565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016122a8565b602081015160005b81518110156123e357600082828151811061236d5761236d614962565b6020026020010151905061238b81600261357e90919063ffffffff16565b156123da5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612350565b50815160005b8151811015610e0b57600082828151811061240657612406614962565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612476576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61248160028261355c565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a1506001016123e9565b60005b8151811015610f0d5760008282815181106124f4576124f4614962565b6020026020010151600001519050600083838151811061251657612516614962565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526007845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016124d7565b604080518082019091526000808252602082015260008390036125ff57506040805180820190915267ffffffffffffffff8216815260006020820152610b44565b600061260b8486614ae6565b9050600061261c8560048189614b2c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016126b957808060200190518101906126b09190614b56565b92505050610b44565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601612735576040518060400160405280828060200190518101906127219190614b82565b815260006020909101529250610b44915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610f0d576121fc816135a0565b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128479190614bb5565b5050509150506000811215612888576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000819050600085602001518473ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129039190614c05565b61290d9190614c22565b905060248160ff16111561294257612926602482614c3b565b61293190600a614d74565b61293b90836148bf565b9150612965565b61294d816024614c3b565b61295890600a614d74565b61296290836148a8565b91505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211156129bb576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff42166020820152949350505050565b836040015163ffffffff16831115612a555760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610f8e565b836020015161ffff16821115612a97576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e0b84610200015182612767565b6000808083815b81811015612d76576000878783818110612ac957612ac9614962565b905060400201803603810190612adf9190614d83565b67ffffffffffffffff8c166000908152600960209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090612c05576101208d0151612bcc9061ffff16662386f26fc100006148a8565b612bd69088614ac0565b96508c610140015186612be99190614dbc565b95508c610160015185612bfc9190614dbc565b94505050612d6e565b604081015160009061ffff1615612cbe5760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614612c61578351612c5a90611b8a565b9050612c64565b508a5b620186a0836040015161ffff16612ca68660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661365390919063ffffffff16565b612cb091906148a8565b612cba91906148bf565b9150505b6060820151612ccd9088614dbc565b9650816080015186612cdf9190614dbc565b8251909650600090612cfe9063ffffffff16662386f26fc100006148a8565b905080821015612d1d57612d12818a614ac0565b985050505050612d6e565b6000836020015163ffffffff16662386f26fc10000612d3c91906148a8565b905080831115612d5c57612d50818b614ac0565b99505050505050612d6e565b612d66838b614ac0565b995050505050505b600101612aad565b505096509650969350505050565b60008063ffffffff8316612d9960e0866148a8565b612da5876101c0614ac0565b612daf9190614ac0565b612db99190614ac0565b905060008760c0015163ffffffff168860e0015161ffff1683612ddc91906148a8565b612de69190614ac0565b61010089015190915061ffff16612e0d6dffffffffffffffffffffffffffff8916836148a8565b612e1791906148a8565b612e2790655af3107a40006148a8565b98975050505050505050565b60408051808201909152600080825260208201526000612e5f858585610180015163ffffffff166125be565b9050826060015163ffffffff1681600001511115612ea9576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e001518015612ebd57508060200151155b15610b41576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603612f73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610f8e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015610f0d57600082828151811061300957613009614962565b60200260200101519050600083838151811061302757613027614962565b60200260200101516000015190506000826020015190508167ffffffffffffffff1660001480613060575061018081015163ffffffff16155b806130b257506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806130c85750602081610160015163ffffffff16105b806130e75750806060015163ffffffff1681610180015163ffffffff16115b1561312a576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610f8e565b67ffffffffffffffff82166000908152600860205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036131d2578167ffffffffffffffff167fa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d13577826040516131c59190613d0f565b60405180910390a2613215565b8167ffffffffffffffff167fa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad938260405161320c9190613d0f565b60405180910390a25b80600860008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101a08201518160010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612fec565b60608160000180548060200260200160405190810160405280929190818152602001828054801561352157602002820191906000526020600020905b81548152602001906001019080831161350d575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b44565b6000610b448373ffffffffffffffffffffffffffffffffffffffff8416613690565b6000610b448373ffffffffffffffffffffffffffffffffffffffff84166136df565b600081516020146135df57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610f8e91906138bd565b6000828060200190518101906135f59190614b82565b905073ffffffffffffffffffffffffffffffffffffffff81118061361a575061040081105b15610eea57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610f8e91906138bd565b6000670de0b6b3a7640000613686837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166148a8565b610b4491906148bf565b60008181526001830160205260408120546136d757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610eea565b506000610eea565b600081815260018301602052604081205480156137c8576000613703600183614ad3565b855490915060009061371790600190614ad3565b905081811461377c57600086600001828154811061373757613737614962565b906000526020600020015490508087600001848154811061375a5761375a614962565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061378d5761378d614dd9565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610eea565b6000915050610eea565b5092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137fd57600080fd5b919050565b60008060006060848603121561381757600080fd5b613820846137d9565b925060208401359150613835604085016137d9565b90509250925092565b60006020828403121561385057600080fd5b610b44826137d9565b6000815180845260005b8181101561387f57602081850181015186830182015201613863565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b446020830184613859565b6020808252825182820181905260009190848201906040850190845b8181101561391e57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016138ec565b50909695505050505050565b60006020828403121561393c57600080fd5b813567ffffffffffffffff81111561395357600080fd5b820160408185031215610b4457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156139b7576139b7613965565b60405290565b60405160c0810167ffffffffffffffff811182821017156139b7576139b7613965565b604051610220810167ffffffffffffffff811182821017156139b7576139b7613965565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613a4b57613a4b613965565b604052919050565b600067ffffffffffffffff821115613a6d57613a6d613965565b5060051b60200190565b60ff81168114610e2257600080fd5b60006020808385031215613a9957600080fd5b823567ffffffffffffffff811115613ab057600080fd5b8301601f81018513613ac157600080fd5b8035613ad4613acf82613a53565b613a04565b81815260609182028301840191848201919088841115613af357600080fd5b938501935b83851015613b935784890381811215613b115760008081fd5b613b19613994565b613b22876137d9565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084011215613b565760008081fd5b613b5e613994565b9250613b6b8989016137d9565b8352870135613b7981613a77565b828901528088019190915283529384019391850191613af8565b50979650505050505050565b60008083601f840112613bb157600080fd5b50813567ffffffffffffffff811115613bc957600080fd5b6020830191508360208260051b8501011115611b8357600080fd5b60008060208385031215613bf757600080fd5b823567ffffffffffffffff811115613c0e57600080fd5b613c1a85828601613b9f565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015613c9457613c8484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101613c43565b5091979650505050505050565b803567ffffffffffffffff811681146137fd57600080fd5b600060208284031215613ccb57600080fd5b610b4482613ca1565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610eea565b81511515815261022081016020830151613d2f602084018261ffff169052565b506040830151613d47604084018263ffffffff169052565b506060830151613d5f606084018263ffffffff169052565b506080830151613d77608084018263ffffffff169052565b5060a0830151613d8d60a084018261ffff169052565b5060c0830151613da560c084018263ffffffff169052565b5060e0830151613dbb60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501518216908401526101a08085015167ffffffffffffffff16908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146137fd57600080fd5b803561ffff811681146137fd57600080fd5b8015158114610e2257600080fd5b80356137fd81613e9b565b600082601f830112613ec557600080fd5b81356020613ed5613acf83613a53565b82815260069290921b84018101918181019086841115613ef457600080fd5b8286015b84811015613f415760408189031215613f115760008081fd5b613f19613994565b613f2282613ca1565b8152613f2f8583016137d9565b81860152835291830191604001613ef8565b509695505050505050565b60008060408385031215613f5f57600080fd5b67ffffffffffffffff83351115613f7557600080fd5b83601f843585010112613f8757600080fd5b613f97613acf8435850135613a53565b8335840180358083526020808401939260059290921b90910101861015613fbd57600080fd5b602085358601015b85358601803560051b016020018110156141ca5767ffffffffffffffff81351115613fef57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a0301121561402857600080fd5b614030613994565b61403c60208301613ca1565b815267ffffffffffffffff6040830135111561405757600080fd5b88603f60408401358401011261406c57600080fd5b614082613acf6020604085013585010135613a53565b6020604084810135850182810135808552928401939260e00201018b10156140a957600080fd5b6040808501358501015b6040858101358601602081013560e00201018110156141ab5760e0818d0312156140dc57600080fd5b6140e4613994565b6140ed826137d9565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f0301121561412157600080fd5b6141296139bd565b61413560208401613e75565b815261414360408401613e75565b602082015261415460608401613e89565b604082015261416560808401613e75565b606082015261417660a08401613e75565b608082015261418860c0840135613e9b565b60c083013560a0820152602082810191909152908452929092019160e0016140b3565b5080602084015250508085525050602083019250602081019050613fc5565b5092505067ffffffffffffffff602084013511156141e757600080fd5b6141f78460208501358501613eb4565b90509250929050565b600082601f83011261421157600080fd5b81356020614221613acf83613a53565b8083825260208201915060208460051b87010193508684111561424357600080fd5b602086015b84811015613f4157614259816137d9565b8352918301918301614248565b6000806040838503121561427957600080fd5b823567ffffffffffffffff8082111561429157600080fd5b61429d86838701614200565b935060208501359150808211156142b357600080fd5b506142c085828601614200565b9150509250929050565b600080604083850312156142dd57600080fd5b6142e683613ca1565b91506141f7602084016137d9565b60006020828403121561430657600080fd5b813567ffffffffffffffff8082111561431e57600080fd5b908301906040828603121561433257600080fd5b61433a613994565b82358281111561434957600080fd5b61435587828601614200565b82525060208301358281111561436a57600080fd5b61437687828601614200565b60208301525095945050505050565b6000602080838503121561439857600080fd5b823567ffffffffffffffff8111156143af57600080fd5b8301601f810185136143c057600080fd5b80356143ce613acf82613a53565b81815260069190911b820183019083810190878311156143ed57600080fd5b928401925b8284101561443f576040848903121561440b5760008081fd5b614413613994565b61441c856137d9565b8152614429868601613ca1565b81870152825260409390930192908401906143f2565b979650505050505050565b60008060008060006080868803121561446257600080fd5b61446b86613ca1565b9450614479602087016137d9565b935060408601359250606086013567ffffffffffffffff8082111561449d57600080fd5b818801915088601f8301126144b157600080fd5b8135818111156144c057600080fd5b8960208285010111156144d257600080fd5b9699959850939650602001949392505050565b83815282151560208201526060604082015260006145066060830184613859565b95945050505050565b60008060008060006060868803121561452757600080fd5b61453086613ca1565b9450602086013567ffffffffffffffff8082111561454d57600080fd5b61455989838a01613b9f565b9096509450604088013591508082111561457257600080fd5b818801915088601f83011261458657600080fd5b81358181111561459557600080fd5b8960208260061b85010111156144d257600080fd5b600080604083850312156145bd57600080fd5b6145c683613ca1565b9150602083013567ffffffffffffffff8111156145e257600080fd5b830160a081860312156145f457600080fd5b809150509250929050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146137fd57600080fd5b6000602080838503121561464257600080fd5b823567ffffffffffffffff81111561465957600080fd5b8301601f8101851361466a57600080fd5b8035614678613acf82613a53565b818152610240918202830184019184820191908884111561469857600080fd5b938501935b83851015613b9357848903818112156146b65760008081fd5b6146be613994565b6146c787613ca1565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156146fc5760008081fd5b6147046139e0565b9250614711898901613ea9565b83526040614720818a01613e89565b8a8501526060614731818b01613e75565b8286015260809150614744828b01613e75565b9085015260a06147558a8201613e75565b8286015260c09150614768828b01613e89565b9085015260e06147798a8201613e75565b82860152610100915061478d828b01613e89565b9085015261012061479f8a8201613e89565b8286015261014091506147b3828b01613e89565b908501526101606147c58a8201613e75565b8286015261018091506147d9828b01613e75565b908501526101a06147eb8a8201613e75565b828601526101c091506147ff828b01613ca1565b908501526101e06148118a8201613e75565b828601526102009150614825828b01613ea9565b908501526148348983016145ff565b9084015250808801919091528352938401939185019161469d565b6000806040838503121561486257600080fd5b61486b836137d9565b91506141f760208401613ca1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610eea57610eea614879565b6000826148f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261492f57600080fd5b83018035915067ffffffffffffffff82111561494a57600080fd5b6020019150600681901b3603821315611b8357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146137fd57600080fd5b6000604082840312156149cf57600080fd5b6149d7613994565b6149e0836137d9565b81526149ee60208401614991565b60208201529392505050565b600060408284031215614a0c57600080fd5b614a14613994565b6149e083613ca1565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614a5157600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614a9057600080fd5b83018035915067ffffffffffffffff821115614aab57600080fd5b602001915036819003821315611b8357600080fd5b80820180821115610eea57610eea614879565b81810381811115610eea57610eea614879565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015613e6d5760049490940360031b84901b1690921692915050565b60008085851115614b3c57600080fd5b83861115614b4957600080fd5b5050820193919092039150565b600060408284031215614b6857600080fd5b614b70613994565b8251815260208301516149ee81613e9b565b600060208284031215614b9457600080fd5b5051919050565b805169ffffffffffffffffffff811681146137fd57600080fd5b600080600080600060a08688031215614bcd57600080fd5b614bd686614b9b565b9450602086015193506040860151925060608601519150614bf960808701614b9b565b90509295509295909350565b600060208284031215614c1757600080fd5b8151610b4481613a77565b60ff8181168382160190811115610eea57610eea614879565b60ff8281168282160390811115610eea57610eea614879565b600181815b80851115614cad57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614c9357614c93614879565b80851615614ca057918102915b93841c9390800290614c59565b509250929050565b600082614cc457506001610eea565b81614cd157506000610eea565b8160018114614ce75760028114614cf157614d0d565b6001915050610eea565b60ff841115614d0257614d02614879565b50506001821b610eea565b5060208310610133831016604e8410600b8410161715614d30575081810a610eea565b614d3a8383614c54565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614d6c57614d6c614879565b029392505050565b6000610b4460ff841683614cb5565b600060408284031215614d9557600080fd5b614d9d613994565b614da6836137d9565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156137d2576137d2614879565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var PriceRegistryABI = PriceRegistryMetaData.ABI var PriceRegistryBin = PriceRegistryMetaData.Bin -func DeployPriceRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, priceUpdaters []common.Address, feeTokens []common.Address, stalenessThreshold uint32, tokenPriceFeeds []PriceRegistryTokenPriceFeedUpdate) (common.Address, *types.Transaction, *PriceRegistry, error) { +func DeployPriceRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig PriceRegistryStaticConfig, priceUpdaters []common.Address, feeTokens []common.Address, tokenPriceFeeds []PriceRegistryTokenPriceFeedUpdate, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (common.Address, *types.Transaction, *PriceRegistry, error) { parsed, err := PriceRegistryMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -83,7 +163,7 @@ func DeployPriceRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(PriceRegistryBin), backend, priceUpdaters, feeTokens, stalenessThreshold, tokenPriceFeeds) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(PriceRegistryBin), backend, staticConfig, priceUpdaters, feeTokens, tokenPriceFeeds, tokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs, destChainConfigArgs) if err != nil { return common.Address{}, nil, nil, err } @@ -250,6 +330,28 @@ func (_PriceRegistry *PriceRegistryCallerSession) GetAllAuthorizedCallers() ([]c return _PriceRegistry.Contract.GetAllAuthorizedCallers(&_PriceRegistry.CallOpts) } +func (_PriceRegistry *PriceRegistryCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (PriceRegistryDestChainConfig, error) { + var out []interface{} + err := _PriceRegistry.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) + + if err != nil { + return *new(PriceRegistryDestChainConfig), err + } + + out0 := *abi.ConvertType(out[0], new(PriceRegistryDestChainConfig)).(*PriceRegistryDestChainConfig) + + return out0, err + +} + +func (_PriceRegistry *PriceRegistrySession) GetDestChainConfig(destChainSelector uint64) (PriceRegistryDestChainConfig, error) { + return _PriceRegistry.Contract.GetDestChainConfig(&_PriceRegistry.CallOpts, destChainSelector) +} + +func (_PriceRegistry *PriceRegistryCallerSession) GetDestChainConfig(destChainSelector uint64) (PriceRegistryDestChainConfig, error) { + return _PriceRegistry.Contract.GetDestChainConfig(&_PriceRegistry.CallOpts, destChainSelector) +} + func (_PriceRegistry *PriceRegistryCaller) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) { var out []interface{} err := _PriceRegistry.contract.Call(opts, &out, "getDestinationChainGasPrice", destChainSelector) @@ -294,26 +396,48 @@ func (_PriceRegistry *PriceRegistryCallerSession) GetFeeTokens() ([]common.Addre return _PriceRegistry.Contract.GetFeeTokens(&_PriceRegistry.CallOpts) } -func (_PriceRegistry *PriceRegistryCaller) GetStalenessThreshold(opts *bind.CallOpts) (*big.Int, error) { +func (_PriceRegistry *PriceRegistryCaller) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getStalenessThreshold") + err := _PriceRegistry.contract.Call(opts, &out, "getPremiumMultiplierWeiPerEth", token) if err != nil { - return *new(*big.Int), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_PriceRegistry *PriceRegistrySession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { + return _PriceRegistry.Contract.GetPremiumMultiplierWeiPerEth(&_PriceRegistry.CallOpts, token) +} + +func (_PriceRegistry *PriceRegistryCallerSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { + return _PriceRegistry.Contract.GetPremiumMultiplierWeiPerEth(&_PriceRegistry.CallOpts, token) +} + +func (_PriceRegistry *PriceRegistryCaller) GetStaticConfig(opts *bind.CallOpts) (PriceRegistryStaticConfig, error) { + var out []interface{} + err := _PriceRegistry.contract.Call(opts, &out, "getStaticConfig") + + if err != nil { + return *new(PriceRegistryStaticConfig), err + } + + out0 := *abi.ConvertType(out[0], new(PriceRegistryStaticConfig)).(*PriceRegistryStaticConfig) return out0, err } -func (_PriceRegistry *PriceRegistrySession) GetStalenessThreshold() (*big.Int, error) { - return _PriceRegistry.Contract.GetStalenessThreshold(&_PriceRegistry.CallOpts) +func (_PriceRegistry *PriceRegistrySession) GetStaticConfig() (PriceRegistryStaticConfig, error) { + return _PriceRegistry.Contract.GetStaticConfig(&_PriceRegistry.CallOpts) } -func (_PriceRegistry *PriceRegistryCallerSession) GetStalenessThreshold() (*big.Int, error) { - return _PriceRegistry.Contract.GetStalenessThreshold(&_PriceRegistry.CallOpts) +func (_PriceRegistry *PriceRegistryCallerSession) GetStaticConfig() (PriceRegistryStaticConfig, error) { + return _PriceRegistry.Contract.GetStaticConfig(&_PriceRegistry.CallOpts) } func (_PriceRegistry *PriceRegistryCaller) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, @@ -412,6 +536,50 @@ func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPrices(tokens []common return _PriceRegistry.Contract.GetTokenPrices(&_PriceRegistry.CallOpts, tokens) } +func (_PriceRegistry *PriceRegistryCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { + var out []interface{} + err := _PriceRegistry.contract.Call(opts, &out, "getTokenTransferFeeConfig", destChainSelector, token) + + if err != nil { + return *new(PriceRegistryTokenTransferFeeConfig), err + } + + out0 := *abi.ConvertType(out[0], new(PriceRegistryTokenTransferFeeConfig)).(*PriceRegistryTokenTransferFeeConfig) + + return out0, err + +} + +func (_PriceRegistry *PriceRegistrySession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { + return _PriceRegistry.Contract.GetTokenTransferFeeConfig(&_PriceRegistry.CallOpts, destChainSelector, token) +} + +func (_PriceRegistry *PriceRegistryCallerSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { + return _PriceRegistry.Contract.GetTokenTransferFeeConfig(&_PriceRegistry.CallOpts, destChainSelector, token) +} + +func (_PriceRegistry *PriceRegistryCaller) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + var out []interface{} + err := _PriceRegistry.contract.Call(opts, &out, "getValidatedFee", destChainSelector, message) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_PriceRegistry *PriceRegistrySession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _PriceRegistry.Contract.GetValidatedFee(&_PriceRegistry.CallOpts, destChainSelector, message) +} + +func (_PriceRegistry *PriceRegistryCallerSession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _PriceRegistry.Contract.GetValidatedFee(&_PriceRegistry.CallOpts, destChainSelector, message) +} + func (_PriceRegistry *PriceRegistryCaller) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { var out []interface{} err := _PriceRegistry.contract.Call(opts, &out, "getValidatedTokenPrice", token) @@ -456,6 +624,37 @@ func (_PriceRegistry *PriceRegistryCallerSession) Owner() (common.Address, error return _PriceRegistry.Contract.Owner(&_PriceRegistry.CallOpts) } +func (_PriceRegistry *PriceRegistryCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, + + error) { + var out []interface{} + err := _PriceRegistry.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs) + + outstruct := new(ProcessMessageArgs) + if err != nil { + return *outstruct, err + } + + outstruct.MsgFeeJuels = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.IsOutOfOrderExecution = *abi.ConvertType(out[1], new(bool)).(*bool) + outstruct.ConvertedExtraArgs = *abi.ConvertType(out[2], new([]byte)).(*[]byte) + + return *outstruct, err + +} + +func (_PriceRegistry *PriceRegistrySession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, + + error) { + return _PriceRegistry.Contract.ProcessMessageArgs(&_PriceRegistry.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) +} + +func (_PriceRegistry *PriceRegistryCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, + + error) { + return _PriceRegistry.Contract.ProcessMessageArgs(&_PriceRegistry.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) +} + func (_PriceRegistry *PriceRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} err := _PriceRegistry.contract.Call(opts, &out, "typeAndVersion") @@ -478,6 +677,26 @@ func (_PriceRegistry *PriceRegistryCallerSession) TypeAndVersion() (string, erro return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) } +func (_PriceRegistry *PriceRegistryCaller) ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { + var out []interface{} + err := _PriceRegistry.contract.Call(opts, &out, "validatePoolReturnData", destChainSelector, rampTokenAmounts, sourceTokenAmounts) + + if err != nil { + return err + } + + return err + +} + +func (_PriceRegistry *PriceRegistrySession) ValidatePoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { + return _PriceRegistry.Contract.ValidatePoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) +} + +func (_PriceRegistry *PriceRegistryCallerSession) ValidatePoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { + return _PriceRegistry.Contract.ValidatePoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) +} + func (_PriceRegistry *PriceRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { return _PriceRegistry.contract.Transact(opts, "acceptOwnership") } @@ -502,6 +721,18 @@ func (_PriceRegistry *PriceRegistryTransactorSession) ApplyAuthorizedCallerUpdat return _PriceRegistry.Contract.ApplyAuthorizedCallerUpdates(&_PriceRegistry.TransactOpts, authorizedCallerArgs) } +func (_PriceRegistry *PriceRegistryTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { + return _PriceRegistry.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) +} + +func (_PriceRegistry *PriceRegistrySession) ApplyDestChainConfigUpdates(destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { + return _PriceRegistry.Contract.ApplyDestChainConfigUpdates(&_PriceRegistry.TransactOpts, destChainConfigArgs) +} + +func (_PriceRegistry *PriceRegistryTransactorSession) ApplyDestChainConfigUpdates(destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { + return _PriceRegistry.Contract.ApplyDestChainConfigUpdates(&_PriceRegistry.TransactOpts, destChainConfigArgs) +} + func (_PriceRegistry *PriceRegistryTransactor) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { return _PriceRegistry.contract.Transact(opts, "applyFeeTokensUpdates", feeTokensToAdd, feeTokensToRemove) } @@ -514,6 +745,30 @@ func (_PriceRegistry *PriceRegistryTransactorSession) ApplyFeeTokensUpdates(feeT return _PriceRegistry.Contract.ApplyFeeTokensUpdates(&_PriceRegistry.TransactOpts, feeTokensToAdd, feeTokensToRemove) } +func (_PriceRegistry *PriceRegistryTransactor) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _PriceRegistry.contract.Transact(opts, "applyPremiumMultiplierWeiPerEthUpdates", premiumMultiplierWeiPerEthArgs) +} + +func (_PriceRegistry *PriceRegistrySession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _PriceRegistry.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_PriceRegistry.TransactOpts, premiumMultiplierWeiPerEthArgs) +} + +func (_PriceRegistry *PriceRegistryTransactorSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _PriceRegistry.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_PriceRegistry.TransactOpts, premiumMultiplierWeiPerEthArgs) +} + +func (_PriceRegistry *PriceRegistryTransactor) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _PriceRegistry.contract.Transact(opts, "applyTokenTransferFeeConfigUpdates", tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +} + +func (_PriceRegistry *PriceRegistrySession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _PriceRegistry.Contract.ApplyTokenTransferFeeConfigUpdates(&_PriceRegistry.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +} + +func (_PriceRegistry *PriceRegistryTransactorSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _PriceRegistry.Contract.ApplyTokenTransferFeeConfigUpdates(&_PriceRegistry.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +} + func (_PriceRegistry *PriceRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _PriceRegistry.contract.Transact(opts, "transferOwnership", to) } @@ -784,8 +1039,8 @@ func (_PriceRegistry *PriceRegistryFilterer) ParseAuthorizedCallerRemoved(log ty return event, nil } -type PriceRegistryFeeTokenAddedIterator struct { - Event *PriceRegistryFeeTokenAdded +type PriceRegistryDestChainAddedIterator struct { + Event *PriceRegistryDestChainAdded contract *bind.BoundContract event string @@ -796,7 +1051,7 @@ type PriceRegistryFeeTokenAddedIterator struct { fail error } -func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { +func (it *PriceRegistryDestChainAddedIterator) Next() bool { if it.fail != nil { return false @@ -805,7 +1060,7 @@ func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenAdded) + it.Event = new(PriceRegistryDestChainAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -820,7 +1075,7 @@ func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenAdded) + it.Event = new(PriceRegistryDestChainAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -835,42 +1090,43 @@ func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { } } -func (it *PriceRegistryFeeTokenAddedIterator) Error() error { +func (it *PriceRegistryDestChainAddedIterator) Error() error { return it.fail } -func (it *PriceRegistryFeeTokenAddedIterator) Close() error { +func (it *PriceRegistryDestChainAddedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryFeeTokenAdded struct { - FeeToken common.Address - Raw types.Log +type PriceRegistryDestChainAdded struct { + DestChainSelector uint64 + DestChainConfig PriceRegistryDestChainConfig + Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) { +func (_PriceRegistry *PriceRegistryFilterer) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainAddedIterator, error) { - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenAdded", feeTokenRule) + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "DestChainAdded", destChainSelectorRule) if err != nil { return nil, err } - return &PriceRegistryFeeTokenAddedIterator{contract: _PriceRegistry.contract, event: "FeeTokenAdded", logs: logs, sub: sub}, nil + return &PriceRegistryDestChainAddedIterator{contract: _PriceRegistry.contract, event: "DestChainAdded", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { +func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenAdded", feeTokenRule) + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "DestChainAdded", destChainSelectorRule) if err != nil { return nil, err } @@ -880,8 +1136,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.Watch select { case log := <-logs: - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { + event := new(PriceRegistryDestChainAdded) + if err := _PriceRegistry.contract.UnpackLog(event, "DestChainAdded", log); err != nil { return err } event.Raw = log @@ -902,17 +1158,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.Watch }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) { - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { +func (_PriceRegistry *PriceRegistryFilterer) ParseDestChainAdded(log types.Log) (*PriceRegistryDestChainAdded, error) { + event := new(PriceRegistryDestChainAdded) + if err := _PriceRegistry.contract.UnpackLog(event, "DestChainAdded", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryFeeTokenRemovedIterator struct { - Event *PriceRegistryFeeTokenRemoved +type PriceRegistryDestChainConfigUpdatedIterator struct { + Event *PriceRegistryDestChainConfigUpdated contract *bind.BoundContract event string @@ -923,7 +1179,7 @@ type PriceRegistryFeeTokenRemovedIterator struct { fail error } -func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { +func (it *PriceRegistryDestChainConfigUpdatedIterator) Next() bool { if it.fail != nil { return false @@ -932,7 +1188,7 @@ func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenRemoved) + it.Event = new(PriceRegistryDestChainConfigUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -947,7 +1203,7 @@ func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenRemoved) + it.Event = new(PriceRegistryDestChainConfigUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -962,42 +1218,43 @@ func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { } } -func (it *PriceRegistryFeeTokenRemovedIterator) Error() error { +func (it *PriceRegistryDestChainConfigUpdatedIterator) Error() error { return it.fail } -func (it *PriceRegistryFeeTokenRemovedIterator) Close() error { +func (it *PriceRegistryDestChainConfigUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryFeeTokenRemoved struct { - FeeToken common.Address - Raw types.Log +type PriceRegistryDestChainConfigUpdated struct { + DestChainSelector uint64 + DestChainConfig PriceRegistryDestChainConfig + Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) { +func (_PriceRegistry *PriceRegistryFilterer) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainConfigUpdatedIterator, error) { - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenRemoved", feeTokenRule) + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) if err != nil { return nil, err } - return &PriceRegistryFeeTokenRemovedIterator{contract: _PriceRegistry.contract, event: "FeeTokenRemoved", logs: logs, sub: sub}, nil + return &PriceRegistryDestChainConfigUpdatedIterator{contract: _PriceRegistry.contract, event: "DestChainConfigUpdated", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { +func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenRemoved", feeTokenRule) + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) if err != nil { return nil, err } @@ -1007,8 +1264,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.Wat select { case log := <-logs: - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { + event := new(PriceRegistryDestChainConfigUpdated) + if err := _PriceRegistry.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { return err } event.Raw = log @@ -1029,17 +1286,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.Wat }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) { - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { +func (_PriceRegistry *PriceRegistryFilterer) ParseDestChainConfigUpdated(log types.Log) (*PriceRegistryDestChainConfigUpdated, error) { + event := new(PriceRegistryDestChainConfigUpdated) + if err := _PriceRegistry.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryOwnershipTransferRequestedIterator struct { - Event *PriceRegistryOwnershipTransferRequested +type PriceRegistryFeeTokenAddedIterator struct { + Event *PriceRegistryFeeTokenAdded contract *bind.BoundContract event string @@ -1050,7 +1307,7 @@ type PriceRegistryOwnershipTransferRequestedIterator struct { fail error } -func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { +func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { if it.fail != nil { return false @@ -1059,7 +1316,7 @@ func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferRequested) + it.Event = new(PriceRegistryFeeTokenAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1074,7 +1331,7 @@ func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferRequested) + it.Event = new(PriceRegistryFeeTokenAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1089,51 +1346,42 @@ func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { } } -func (it *PriceRegistryOwnershipTransferRequestedIterator) Error() error { +func (it *PriceRegistryFeeTokenAddedIterator) Error() error { return it.fail } -func (it *PriceRegistryOwnershipTransferRequestedIterator) Close() error { +func (it *PriceRegistryFeeTokenAddedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log +type PriceRegistryFeeTokenAdded struct { + FeeToken common.Address + Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, error) { +func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) { - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenAdded", feeTokenRule) if err != nil { return nil, err } - return &PriceRegistryOwnershipTransferRequestedIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &PriceRegistryFeeTokenAddedIterator{contract: _PriceRegistry.contract, event: "FeeTokenAdded", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenAdded", feeTokenRule) if err != nil { return nil, err } @@ -1143,8 +1391,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opt select { case log := <-logs: - event := new(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(PriceRegistryFeeTokenAdded) + if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { return err } event.Raw = log @@ -1165,17 +1413,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opt }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) { - event := new(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) { + event := new(PriceRegistryFeeTokenAdded) + if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryOwnershipTransferredIterator struct { - Event *PriceRegistryOwnershipTransferred +type PriceRegistryFeeTokenRemovedIterator struct { + Event *PriceRegistryFeeTokenRemoved contract *bind.BoundContract event string @@ -1186,7 +1434,7 @@ type PriceRegistryOwnershipTransferredIterator struct { fail error } -func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { +func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { if it.fail != nil { return false @@ -1195,7 +1443,270 @@ func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferred) + it.Event = new(PriceRegistryFeeTokenRemoved) + 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(PriceRegistryFeeTokenRemoved) + 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 *PriceRegistryFeeTokenRemovedIterator) Error() error { + return it.fail +} + +func (it *PriceRegistryFeeTokenRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PriceRegistryFeeTokenRemoved struct { + FeeToken common.Address + Raw types.Log +} + +func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) { + + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenRemoved", feeTokenRule) + if err != nil { + return nil, err + } + return &PriceRegistryFeeTokenRemovedIterator{contract: _PriceRegistry.contract, event: "FeeTokenRemoved", logs: logs, sub: sub}, nil +} + +func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { + + var feeTokenRule []interface{} + for _, feeTokenItem := range feeToken { + feeTokenRule = append(feeTokenRule, feeTokenItem) + } + + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenRemoved", feeTokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PriceRegistryFeeTokenRemoved) + if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", 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 (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) { + event := new(PriceRegistryFeeTokenRemoved) + if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type PriceRegistryOwnershipTransferRequestedIterator struct { + Event *PriceRegistryOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PriceRegistryOwnershipTransferRequested) + 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(PriceRegistryOwnershipTransferRequested) + 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 *PriceRegistryOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *PriceRegistryOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PriceRegistryOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &PriceRegistryOwnershipTransferRequestedIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PriceRegistryOwnershipTransferRequested) + if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", 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 (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) { + event := new(PriceRegistryOwnershipTransferRequested) + if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type PriceRegistryOwnershipTransferredIterator struct { + Event *PriceRegistryOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PriceRegistryOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1310,6 +1821,134 @@ func (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferred(log types return event, nil } +type PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator struct { + Event *PriceRegistryPremiumMultiplierWeiPerEthUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) + 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(PriceRegistryPremiumMultiplierWeiPerEthUpdated) + 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 *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Error() error { + return it.fail +} + +func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PriceRegistryPremiumMultiplierWeiPerEthUpdated struct { + Token common.Address + PremiumMultiplierWeiPerEth uint64 + Raw types.Log +} + +func (_PriceRegistry *PriceRegistryFilterer) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) + if err != nil { + return nil, err + } + return &PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator{contract: _PriceRegistry.contract, event: "PremiumMultiplierWeiPerEthUpdated", logs: logs, sub: sub}, nil +} + +func (_PriceRegistry *PriceRegistryFilterer) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { + + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) + if err := _PriceRegistry.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) { + event := new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) + if err := _PriceRegistry.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type PriceRegistryPriceFeedPerTokenUpdatedIterator struct { Event *PriceRegistryPriceFeedPerTokenUpdated @@ -1692,6 +2331,279 @@ func (_PriceRegistry *PriceRegistryFilterer) ParsePriceUpdaterSet(log types.Log) return event, nil } +type PriceRegistryTokenTransferFeeConfigDeletedIterator struct { + Event *PriceRegistryTokenTransferFeeConfigDeleted + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PriceRegistryTokenTransferFeeConfigDeleted) + 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(PriceRegistryTokenTransferFeeConfigDeleted) + 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 *PriceRegistryTokenTransferFeeConfigDeletedIterator) Error() error { + return it.fail +} + +func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PriceRegistryTokenTransferFeeConfigDeleted struct { + DestChainSelector uint64 + Token common.Address + Raw types.Log +} + +func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigDeletedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return &PriceRegistryTokenTransferFeeConfigDeletedIterator{contract: _PriceRegistry.contract, event: "TokenTransferFeeConfigDeleted", logs: logs, sub: sub}, nil +} + +func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PriceRegistryTokenTransferFeeConfigDeleted) + if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", 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 (_PriceRegistry *PriceRegistryFilterer) ParseTokenTransferFeeConfigDeleted(log types.Log) (*PriceRegistryTokenTransferFeeConfigDeleted, error) { + event := new(PriceRegistryTokenTransferFeeConfigDeleted) + if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type PriceRegistryTokenTransferFeeConfigUpdatedIterator struct { + Event *PriceRegistryTokenTransferFeeConfigUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(PriceRegistryTokenTransferFeeConfigUpdated) + 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(PriceRegistryTokenTransferFeeConfigUpdated) + 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 *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Error() error { + return it.fail +} + +func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type PriceRegistryTokenTransferFeeConfigUpdated struct { + DestChainSelector uint64 + Token common.Address + TokenTransferFeeConfig PriceRegistryTokenTransferFeeConfig + Raw types.Log +} + +func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return &PriceRegistryTokenTransferFeeConfigUpdatedIterator{contract: _PriceRegistry.contract, event: "TokenTransferFeeConfigUpdated", logs: logs, sub: sub}, nil +} + +func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + var tokenRule []interface{} + for _, tokenItem := range token { + tokenRule = append(tokenRule, tokenItem) + } + + logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(PriceRegistryTokenTransferFeeConfigUpdated) + if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", 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 (_PriceRegistry *PriceRegistryFilterer) ParseTokenTransferFeeConfigUpdated(log types.Log) (*PriceRegistryTokenTransferFeeConfigUpdated, error) { + event := new(PriceRegistryTokenTransferFeeConfigUpdated) + if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type PriceRegistryUsdPerTokenUpdatedIterator struct { Event *PriceRegistryUsdPerTokenUpdated @@ -1954,6 +2866,11 @@ type GetTokenAndGasPrices struct { TokenPrice *big.Int GasPriceValue *big.Int } +type ProcessMessageArgs struct { + MsgFeeJuels *big.Int + IsOutOfOrderExecution bool + ConvertedExtraArgs []byte +} func (_PriceRegistry *PriceRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { @@ -1961,6 +2878,10 @@ func (_PriceRegistry *PriceRegistry) ParseLog(log types.Log) (generated.AbigenLo return _PriceRegistry.ParseAuthorizedCallerAdded(log) case _PriceRegistry.abi.Events["AuthorizedCallerRemoved"].ID: return _PriceRegistry.ParseAuthorizedCallerRemoved(log) + case _PriceRegistry.abi.Events["DestChainAdded"].ID: + return _PriceRegistry.ParseDestChainAdded(log) + case _PriceRegistry.abi.Events["DestChainConfigUpdated"].ID: + return _PriceRegistry.ParseDestChainConfigUpdated(log) case _PriceRegistry.abi.Events["FeeTokenAdded"].ID: return _PriceRegistry.ParseFeeTokenAdded(log) case _PriceRegistry.abi.Events["FeeTokenRemoved"].ID: @@ -1969,12 +2890,18 @@ func (_PriceRegistry *PriceRegistry) ParseLog(log types.Log) (generated.AbigenLo return _PriceRegistry.ParseOwnershipTransferRequested(log) case _PriceRegistry.abi.Events["OwnershipTransferred"].ID: return _PriceRegistry.ParseOwnershipTransferred(log) + case _PriceRegistry.abi.Events["PremiumMultiplierWeiPerEthUpdated"].ID: + return _PriceRegistry.ParsePremiumMultiplierWeiPerEthUpdated(log) case _PriceRegistry.abi.Events["PriceFeedPerTokenUpdated"].ID: return _PriceRegistry.ParsePriceFeedPerTokenUpdated(log) case _PriceRegistry.abi.Events["PriceUpdaterRemoved"].ID: return _PriceRegistry.ParsePriceUpdaterRemoved(log) case _PriceRegistry.abi.Events["PriceUpdaterSet"].ID: return _PriceRegistry.ParsePriceUpdaterSet(log) + case _PriceRegistry.abi.Events["TokenTransferFeeConfigDeleted"].ID: + return _PriceRegistry.ParseTokenTransferFeeConfigDeleted(log) + case _PriceRegistry.abi.Events["TokenTransferFeeConfigUpdated"].ID: + return _PriceRegistry.ParseTokenTransferFeeConfigUpdated(log) case _PriceRegistry.abi.Events["UsdPerTokenUpdated"].ID: return _PriceRegistry.ParseUsdPerTokenUpdated(log) case _PriceRegistry.abi.Events["UsdPerUnitGasUpdated"].ID: @@ -1993,6 +2920,14 @@ func (PriceRegistryAuthorizedCallerRemoved) Topic() common.Hash { return common.HexToHash("0xc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda77580") } +func (PriceRegistryDestChainAdded) Topic() common.Hash { + return common.HexToHash("0xa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d13577") +} + +func (PriceRegistryDestChainConfigUpdated) Topic() common.Hash { + return common.HexToHash("0xa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad93") +} + func (PriceRegistryFeeTokenAdded) Topic() common.Hash { return common.HexToHash("0xdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23") } @@ -2009,6 +2944,10 @@ func (PriceRegistryOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (PriceRegistryPremiumMultiplierWeiPerEthUpdated) Topic() common.Hash { + return common.HexToHash("0xbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d") +} + func (PriceRegistryPriceFeedPerTokenUpdated) Topic() common.Hash { return common.HexToHash("0x08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464") } @@ -2021,6 +2960,14 @@ func (PriceRegistryPriceUpdaterSet) Topic() common.Hash { return common.HexToHash("0x34a02290b7920078c19f58e94b78c77eb9cc10195b20676e19bd3b82085893b8") } +func (PriceRegistryTokenTransferFeeConfigDeleted) Topic() common.Hash { + return common.HexToHash("0x4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b") +} + +func (PriceRegistryTokenTransferFeeConfigUpdated) Topic() common.Hash { + return common.HexToHash("0x94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5") +} + func (PriceRegistryUsdPerTokenUpdated) Topic() common.Hash { return common.HexToHash("0x52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a") } @@ -2038,11 +2985,15 @@ type PriceRegistryInterface interface { GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) + GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (PriceRegistryDestChainConfig, error) + GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) - GetStalenessThreshold(opts *bind.CallOpts) (*big.Int, error) + GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) + + GetStaticConfig(opts *bind.CallOpts) (PriceRegistryStaticConfig, error) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, @@ -2054,18 +3005,34 @@ type PriceRegistryInterface interface { GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) + GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) + + GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) + GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) Owner(opts *bind.CallOpts) (common.Address, error) + ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, + + error) + TypeAndVersion(opts *bind.CallOpts) (string, error) + ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) + ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) + ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) + ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) + + ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) @@ -2084,6 +3051,18 @@ type PriceRegistryInterface interface { ParseAuthorizedCallerRemoved(log types.Log) (*PriceRegistryAuthorizedCallerRemoved, error) + FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainAddedIterator, error) + + WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) + + ParseDestChainAdded(log types.Log) (*PriceRegistryDestChainAdded, error) + + FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainConfigUpdatedIterator, error) + + WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) + + ParseDestChainConfigUpdated(log types.Log) (*PriceRegistryDestChainConfigUpdated, error) + FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) @@ -2108,6 +3087,12 @@ type PriceRegistryInterface interface { ParseOwnershipTransferred(log types.Log) (*PriceRegistryOwnershipTransferred, error) + FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) + + WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) + + ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) + FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPriceFeedPerTokenUpdatedIterator, error) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) @@ -2126,6 +3111,18 @@ type PriceRegistryInterface interface { ParsePriceUpdaterSet(log types.Log) (*PriceRegistryPriceUpdaterSet, error) + FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigDeletedIterator, error) + + WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) + + ParseTokenTransferFeeConfigDeleted(log types.Log) (*PriceRegistryTokenTransferFeeConfigDeleted, error) + + FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) + + WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) + + ParseTokenTransferFeeConfigUpdated(log types.Log) (*PriceRegistryTokenTransferFeeConfigUpdated, error) + FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryUsdPerTokenUpdatedIterator, error) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, 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 e2485ce9e0..663eacb5dd 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 @@ -10,7 +10,7 @@ commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../ commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin ebd8aac686fa28a71d4212bcd25a28f8f640d50dce5e50498b2f6b8534890b69 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 25a7bf3aa46252844c7afabc15db1051e7b6a717e296fc4c6e2f2f93d16033c5 -evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 918036eebe888df142047ebb3c93ddd9e3d47749bfa25e32dc89f96e1c5f43a4 +evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 9478aedc9f0072fbdafb54a6f82248de1efbcd7bdff18a90d8556b9aaff67455 evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin a8c23c9280a713544eae0a0b8841a9caf97e616338d31ebc62501d8b4ab0eed6 evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 116d5cb8447a1af61664a8d1db2d76086c042a3228337bc5cd49b9abd3e815f7 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 95a93517b01f51c35d82711a0015995f4804820ed67f6b46b785c4c94815df93 @@ -26,7 +26,7 @@ multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Help nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 78b58f4f192db7496e2b6de805d6a2c918b98d4fa62f3c7ed145ef3b5657a40d ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 1588313bb5e781d181a825247d30828f59007700f36b4b9b00391592b06ff4b4 -price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin 0b3e253684d7085aa11f9179b71453b9db9d11cabea41605d5b4ac4128f85bfb +price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin 09cdd37920d6f605c8a264f805bdba183813517169b2b5df4547e995d9ce73f7 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 7b2a47349d3fdb8d8b4e206d68577219deca7fabd1e893686fa8f118ad980d2d report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin c07af8433bf8dbc7981725b18922a9c4e2dea068dd204bc62adc0e926cb499c3 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 42576577e81beea9a069bd9229caaa9a71227fbaef3871a1a2e69fd218216290 diff --git a/core/gethwrappers/ccip/mocks/price_registry_interface.go b/core/gethwrappers/ccip/mocks/price_registry_interface.go index 45e9214737..2a8115cd78 100644 --- a/core/gethwrappers/ccip/mocks/price_registry_interface.go +++ b/core/gethwrappers/ccip/mocks/price_registry_interface.go @@ -104,6 +104,36 @@ func (_m *PriceRegistryInterface) ApplyAuthorizedCallerUpdates(opts *bind.Transa return r0, r1 } +// ApplyDestChainConfigUpdates provides a mock function with given fields: opts, destChainConfigArgs +func (_m *PriceRegistryInterface) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { + ret := _m.Called(opts, destChainConfigArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyDestChainConfigUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error)); ok { + return rf(opts, destChainConfigArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) *types.Transaction); ok { + r0 = rf(opts, destChainConfigArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) error); ok { + r1 = rf(opts, destChainConfigArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ApplyFeeTokensUpdates provides a mock function with given fields: opts, feeTokensToAdd, feeTokensToRemove func (_m *PriceRegistryInterface) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { ret := _m.Called(opts, feeTokensToAdd, feeTokensToRemove) @@ -134,6 +164,66 @@ func (_m *PriceRegistryInterface) ApplyFeeTokensUpdates(opts *bind.TransactOpts, return r0, r1 } +// ApplyPremiumMultiplierWeiPerEthUpdates provides a mock function with given fields: opts, premiumMultiplierWeiPerEthArgs +func (_m *PriceRegistryInterface) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + ret := _m.Called(opts, premiumMultiplierWeiPerEthArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyPremiumMultiplierWeiPerEthUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)); ok { + return rf(opts, premiumMultiplierWeiPerEthArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) *types.Transaction); ok { + r0 = rf(opts, premiumMultiplierWeiPerEthArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) error); ok { + r1 = rf(opts, premiumMultiplierWeiPerEthArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ApplyTokenTransferFeeConfigUpdates provides a mock function with given fields: opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs +func (_m *PriceRegistryInterface) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []price_registry.PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + ret := _m.Called(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + + if len(ret) == 0 { + panic("no return value specified for ApplyTokenTransferFeeConfigUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)); ok { + return rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) *types.Transaction); ok { + r0 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) error); ok { + r1 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ConvertTokenAmount provides a mock function with given fields: opts, fromToken, fromTokenAmount, toToken func (_m *PriceRegistryInterface) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { ret := _m.Called(opts, fromToken, fromTokenAmount, toToken) @@ -224,6 +314,66 @@ func (_m *PriceRegistryInterface) FilterAuthorizedCallerRemoved(opts *bind.Filte return r0, r1 } +// FilterDestChainAdded provides a mock function with given fields: opts, destChainSelector +func (_m *PriceRegistryInterface) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for FilterDestChainAdded") + } + + var r0 *price_registry.PriceRegistryDestChainAddedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryDestChainAddedIterator); ok { + r0 = rf(opts, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainAddedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FilterDestChainConfigUpdated provides a mock function with given fields: opts, destChainSelector +func (_m *PriceRegistryInterface) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for FilterDestChainConfigUpdated") + } + + var r0 *price_registry.PriceRegistryDestChainConfigUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryDestChainConfigUpdatedIterator); ok { + r0 = rf(opts, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainConfigUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FilterFeeTokenAdded provides a mock function with given fields: opts, feeToken func (_m *PriceRegistryInterface) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*price_registry.PriceRegistryFeeTokenAddedIterator, error) { ret := _m.Called(opts, feeToken) @@ -344,6 +494,36 @@ func (_m *PriceRegistryInterface) FilterOwnershipTransferred(opts *bind.FilterOp return r0, r1 } +// FilterPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, token +func (_m *PriceRegistryInterface) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for FilterPremiumMultiplierWeiPerEthUpdated") + } + + var r0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FilterPriceFeedPerTokenUpdated provides a mock function with given fields: opts, token func (_m *PriceRegistryInterface) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, error) { ret := _m.Called(opts, token) @@ -434,6 +614,66 @@ func (_m *PriceRegistryInterface) FilterPriceUpdaterSet(opts *bind.FilterOpts, p return r0, r1 } +// FilterTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, destChainSelector, token +func (_m *PriceRegistryInterface) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for FilterTokenTransferFeeConfigDeleted") + } + + var r0 *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator); ok { + r0 = rf(opts, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FilterTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, destChainSelector, token +func (_m *PriceRegistryInterface) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for FilterTokenTransferFeeConfigUpdated") + } + + var r0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator); ok { + r0 = rf(opts, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // FilterUsdPerTokenUpdated provides a mock function with given fields: opts, token func (_m *PriceRegistryInterface) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryUsdPerTokenUpdatedIterator, error) { ret := _m.Called(opts, token) @@ -524,6 +764,34 @@ func (_m *PriceRegistryInterface) GetAllAuthorizedCallers(opts *bind.CallOpts) ( return r0, r1 } +// GetDestChainConfig provides a mock function with given fields: opts, destChainSelector +func (_m *PriceRegistryInterface) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (price_registry.PriceRegistryDestChainConfig, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetDestChainConfig") + } + + var r0 price_registry.PriceRegistryDestChainConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (price_registry.PriceRegistryDestChainConfig, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) price_registry.PriceRegistryDestChainConfig); ok { + r0 = rf(opts, destChainSelector) + } else { + r0 = ret.Get(0).(price_registry.PriceRegistryDestChainConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetDestinationChainGasPrice provides a mock function with given fields: opts, destChainSelector func (_m *PriceRegistryInterface) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (price_registry.InternalTimestampedPackedUint224, error) { ret := _m.Called(opts, destChainSelector) @@ -582,25 +850,51 @@ func (_m *PriceRegistryInterface) GetFeeTokens(opts *bind.CallOpts) ([]common.Ad return r0, r1 } -// GetStalenessThreshold provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) GetStalenessThreshold(opts *bind.CallOpts) (*big.Int, error) { +// GetPremiumMultiplierWeiPerEth provides a mock function with given fields: opts, token +func (_m *PriceRegistryInterface) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetPremiumMultiplierWeiPerEth") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (uint64, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) uint64); ok { + r0 = rf(opts, token) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetStaticConfig provides a mock function with given fields: opts +func (_m *PriceRegistryInterface) GetStaticConfig(opts *bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error) { ret := _m.Called(opts) if len(ret) == 0 { - panic("no return value specified for GetStalenessThreshold") + panic("no return value specified for GetStaticConfig") } - var r0 *big.Int + var r0 price_registry.PriceRegistryStaticConfig var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (*big.Int, error)); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error)); ok { return rf(opts) } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) *big.Int); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts) price_registry.PriceRegistryStaticConfig); ok { r0 = rf(opts) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } + r0 = ret.Get(0).(price_registry.PriceRegistryStaticConfig) } if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { @@ -726,6 +1020,64 @@ func (_m *PriceRegistryInterface) GetTokenPrices(opts *bind.CallOpts, tokens []c return r0, r1 } +// GetTokenTransferFeeConfig provides a mock function with given fields: opts, destChainSelector, token +func (_m *PriceRegistryInterface) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for GetTokenTransferFeeConfig") + } + + var r0 price_registry.PriceRegistryTokenTransferFeeConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) price_registry.PriceRegistryTokenTransferFeeConfig); ok { + r0 = rf(opts, destChainSelector, token) + } else { + r0 = ret.Get(0).(price_registry.PriceRegistryTokenTransferFeeConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetValidatedFee provides a mock function with given fields: opts, destChainSelector, message +func (_m *PriceRegistryInterface) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message price_registry.ClientEVM2AnyMessage) (*big.Int, error) { + ret := _m.Called(opts, destChainSelector, message) + + if len(ret) == 0 { + panic("no return value specified for GetValidatedFee") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) (*big.Int, error)); ok { + return rf(opts, destChainSelector, message) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) *big.Int); ok { + r0 = rf(opts, destChainSelector, message) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) error); ok { + r1 = rf(opts, destChainSelector, message) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetValidatedTokenPrice provides a mock function with given fields: opts, token func (_m *PriceRegistryInterface) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { ret := _m.Called(opts, token) @@ -846,6 +1198,66 @@ func (_m *PriceRegistryInterface) ParseAuthorizedCallerRemoved(log types.Log) (* return r0, r1 } +// ParseDestChainAdded provides a mock function with given fields: log +func (_m *PriceRegistryInterface) ParseDestChainAdded(log types.Log) (*price_registry.PriceRegistryDestChainAdded, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseDestChainAdded") + } + + var r0 *price_registry.PriceRegistryDestChainAdded + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryDestChainAdded, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryDestChainAdded); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainAdded) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ParseDestChainConfigUpdated provides a mock function with given fields: log +func (_m *PriceRegistryInterface) ParseDestChainConfigUpdated(log types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseDestChainConfigUpdated") + } + + var r0 *price_registry.PriceRegistryDestChainConfigUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryDestChainConfigUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainConfigUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ParseFeeTokenAdded provides a mock function with given fields: log func (_m *PriceRegistryInterface) ParseFeeTokenAdded(log types.Log) (*price_registry.PriceRegistryFeeTokenAdded, error) { ret := _m.Called(log) @@ -996,6 +1408,36 @@ func (_m *PriceRegistryInterface) ParseOwnershipTransferred(log types.Log) (*pri return r0, r1 } +// ParsePremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: log +func (_m *PriceRegistryInterface) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParsePremiumMultiplierWeiPerEthUpdated") + } + + var r0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ParsePriceFeedPerTokenUpdated provides a mock function with given fields: log func (_m *PriceRegistryInterface) ParsePriceFeedPerTokenUpdated(log types.Log) (*price_registry.PriceRegistryPriceFeedPerTokenUpdated, error) { ret := _m.Called(log) @@ -1086,6 +1528,66 @@ func (_m *PriceRegistryInterface) ParsePriceUpdaterSet(log types.Log) (*price_re return r0, r1 } +// ParseTokenTransferFeeConfigDeleted provides a mock function with given fields: log +func (_m *PriceRegistryInterface) ParseTokenTransferFeeConfigDeleted(log types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseTokenTransferFeeConfigDeleted") + } + + var r0 *price_registry.PriceRegistryTokenTransferFeeConfigDeleted + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryTokenTransferFeeConfigDeleted); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigDeleted) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ParseTokenTransferFeeConfigUpdated provides a mock function with given fields: log +func (_m *PriceRegistryInterface) ParseTokenTransferFeeConfigUpdated(log types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseTokenTransferFeeConfigUpdated") + } + + var r0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryTokenTransferFeeConfigUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ParseUsdPerTokenUpdated provides a mock function with given fields: log func (_m *PriceRegistryInterface) ParseUsdPerTokenUpdated(log types.Log) (*price_registry.PriceRegistryUsdPerTokenUpdated, error) { ret := _m.Called(log) @@ -1146,6 +1648,34 @@ func (_m *PriceRegistryInterface) ParseUsdPerUnitGasUpdated(log types.Log) (*pri return r0, r1 } +// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs +func (_m *PriceRegistryInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (price_registry.ProcessMessageArgs, error) { + ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + + if len(ret) == 0 { + panic("no return value specified for ProcessMessageArgs") + } + + var r0 price_registry.ProcessMessageArgs + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (price_registry.ProcessMessageArgs, error)); ok { + return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) price_registry.ProcessMessageArgs); ok { + r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + } else { + r0 = ret.Get(0).(price_registry.ProcessMessageArgs) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) error); ok { + r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // TransferOwnership provides a mock function with given fields: opts, to func (_m *PriceRegistryInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { ret := _m.Called(opts, to) @@ -1264,6 +1794,24 @@ func (_m *PriceRegistryInterface) UpdateTokenPriceFeeds(opts *bind.TransactOpts, return r0, r1 } +// ValidatePoolReturnData provides a mock function with given fields: opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts +func (_m *PriceRegistryInterface) ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount) error { + ret := _m.Called(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + + if len(ret) == 0 { + panic("no return value specified for ValidatePoolReturnData") + } + + var r0 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) error); ok { + r0 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // WatchAuthorizedCallerAdded provides a mock function with given fields: opts, sink func (_m *PriceRegistryInterface) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) { ret := _m.Called(opts, sink) @@ -1324,6 +1872,66 @@ func (_m *PriceRegistryInterface) WatchAuthorizedCallerRemoved(opts *bind.WatchO return r0, r1 } +// WatchDestChainAdded provides a mock function with given fields: opts, sink, destChainSelector +func (_m *PriceRegistryInterface) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for WatchDestChainAdded") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) error); ok { + r1 = rf(opts, sink, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// WatchDestChainConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector +func (_m *PriceRegistryInterface) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for WatchDestChainConfigUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) error); ok { + r1 = rf(opts, sink, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // WatchFeeTokenAdded provides a mock function with given fields: opts, sink, feeToken func (_m *PriceRegistryInterface) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { ret := _m.Called(opts, sink, feeToken) @@ -1444,6 +2052,36 @@ func (_m *PriceRegistryInterface) WatchOwnershipTransferred(opts *bind.WatchOpts return r0, r1 } +// WatchPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, sink, token +func (_m *PriceRegistryInterface) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, token) + + if len(ret) == 0 { + panic("no return value specified for WatchPremiumMultiplierWeiPerEthUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) error); ok { + r1 = rf(opts, sink, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // WatchPriceFeedPerTokenUpdated provides a mock function with given fields: opts, sink, token func (_m *PriceRegistryInterface) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { ret := _m.Called(opts, sink, token) @@ -1534,6 +2172,66 @@ func (_m *PriceRegistryInterface) WatchPriceUpdaterSet(opts *bind.WatchOpts, sin return r0, r1 } +// WatchTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, sink, destChainSelector, token +func (_m *PriceRegistryInterface) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for WatchTokenTransferFeeConfigDeleted") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) error); ok { + r1 = rf(opts, sink, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// WatchTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector, token +func (_m *PriceRegistryInterface) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for WatchTokenTransferFeeConfigUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) error); ok { + r1 = rf(opts, sink, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // WatchUsdPerTokenUpdated provides a mock function with given fields: opts, sink, token func (_m *PriceRegistryInterface) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { ret := _m.Called(opts, sink, token) diff --git a/core/services/ccipcapability/configs/evm/chain_writer.go b/core/services/ccipcapability/configs/evm/chain_writer.go index 6b7696da1e..b112681c64 100644 --- a/core/services/ccipcapability/configs/evm/chain_writer.go +++ b/core/services/ccipcapability/configs/evm/chain_writer.go @@ -61,7 +61,7 @@ func ChainWriterConfigRaw(fromAddress common.Address, maxGasPrice *assets.Wei) e func mustGetMethodName(name string, tabi abi.ABI) (methodName string) { m, ok := tabi.Methods[name] if !ok { - panic(fmt.Sprintf("missing method %s in offrampABI", name)) + panic(fmt.Sprintf("missing method %s in the abi", name)) } return m.Name } diff --git a/core/services/ccipcapability/configs/evm/contract_reader.go b/core/services/ccipcapability/configs/evm/contract_reader.go index 0cf6d21170..085729690d 100644 --- a/core/services/ccipcapability/configs/evm/contract_reader.go +++ b/core/services/ccipcapability/configs/evm/contract_reader.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_multi_onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -20,6 +21,7 @@ var ( onrampABI = evmtypes.MustGetABI(evm_2_evm_multi_onramp.EVM2EVMMultiOnRampABI) capabilitiesRegsitryABI = evmtypes.MustGetABI(kcr.CapabilitiesRegistryABI) ccipConfigABI = evmtypes.MustGetABI(ccip_config.CCIPConfigABI) + priceRegistryABI = evmtypes.MustGetABI(price_registry.PriceRegistryABI) ) // MustSourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp. @@ -127,18 +129,6 @@ func SourceReaderConfig() evmrelaytypes.ChainReaderConfig { ChainSpecificName: mustGetMethodName("getDynamicConfig", onrampABI), ReadType: evmrelaytypes.Method, }, - consts.MethodNameGetDestChainConfig: { - ChainSpecificName: mustGetMethodName("getDestChainConfig", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetPremiumMultiplierWeiPerEth: { - ChainSpecificName: mustGetMethodName("getPremiumMultiplierWeiPerEth", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetTokenTransferFeeConfig: { - ChainSpecificName: mustGetMethodName("getTokenTransferFeeConfig", onrampABI), - ReadType: evmrelaytypes.Method, - }, consts.EventNameCCIPSendRequested: { ChainSpecificName: mustGetEventName(consts.EventNameCCIPSendRequested, onrampABI), ReadType: evmrelaytypes.Event, @@ -150,6 +140,45 @@ func SourceReaderConfig() evmrelaytypes.ChainReaderConfig { }, }, }, + consts.ContractNamePriceRegistry: { + ContractABI: price_registry.PriceRegistryABI, + Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ + // TODO: update with the consts from https://github.com/smartcontractkit/chainlink-ccip/pull/39 + // in a followup. + "GetStaticConfig": { + ChainSpecificName: mustGetMethodName("getStaticConfig", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + "GetDestChainConfig": { + ChainSpecificName: mustGetMethodName("getDestChainConfig", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + "GetPremiumMultiplierWeiPerEth": { + ChainSpecificName: mustGetMethodName("getPremiumMultiplierWeiPerEth", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + "GetTokenTransferFeeConfig": { + ChainSpecificName: mustGetMethodName("getTokenTransferFeeConfig", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + "ProcessMessageArgs": { + ChainSpecificName: mustGetMethodName("processMessageArgs", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + "ValidatePoolReturnData": { + ChainSpecificName: mustGetMethodName("validatePoolReturnData", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + "GetValidatedTokenPrice": { + ChainSpecificName: mustGetMethodName("getValidatedTokenPrice", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + "GetFeeTokens": { + ChainSpecificName: mustGetMethodName("getFeeTokens", priceRegistryABI), + ReadType: evmrelaytypes.Method, + }, + }, + }, }, } } diff --git a/core/services/ocr3/plugins/ccip_integration_tests/helpers.go b/core/services/ocr3/plugins/ccip_integration_tests/helpers.go index 51ef640b5e..18c4c2d17a 100644 --- a/core/services/ocr3/plugins/ccip_integration_tests/helpers.go +++ b/core/services/ocr3/plugins/ccip_integration_tests/helpers.go @@ -115,7 +115,7 @@ func createUniverses( rmnProxy := deployARMProxyContract(t, owner, backend, rmn.Address(), chainID) weth := deployWETHContract(t, owner, backend, chainID) rout := deployRouter(t, owner, backend, weth.Address(), rmnProxy.Address(), chainID) - priceRegistry := deployPriceRegistry(t, owner, backend, linkToken.Address(), weth.Address(), chainID) + priceRegistry := deployPriceRegistry(t, owner, backend, linkToken.Address(), weth.Address(), big.NewInt(1e18), chainID) tokenAdminRegistry := deployTokenAdminRegistry(t, owner, backend, chainID) nonceManager := deployNonceManager(t, owner, backend, chainID) @@ -126,10 +126,8 @@ func createUniverses( owner, backend, evm_2_evm_multi_onramp.EVM2EVMMultiOnRampStaticConfig{ - LinkToken: linkToken.Address(), ChainSelector: getSelector(chainID), RmnProxy: rmnProxy.Address(), - MaxFeeJuelsPerMsg: big.NewInt(1e18), NonceManager: nonceManager.Address(), TokenAdminRegistry: tokenAdminRegistry.Address(), }, @@ -140,21 +138,6 @@ func createUniverses( // so we can set this to any address FeeAggregator: testutils.NewAddress(), }, - // Destination chain configs will be set up later once we have all chains - []evm_2_evm_multi_onramp.EVM2EVMMultiOnRampDestChainConfigArgs{}, - // PremiumMultiplier is always needed if the onramp is enabled - []evm_2_evm_multi_onramp.EVM2EVMMultiOnRampPremiumMultiplierWeiPerEthArgs{ - { - PremiumMultiplierWeiPerEth: 9e17, //0.9 ETH - Token: linkToken.Address(), - }, - { - PremiumMultiplierWeiPerEth: 1e18, - Token: weth.Address(), - }, - }, - //TODO: We'll need to have TransferFeeConfigArgs when we start testing with sending tokens - []evm_2_evm_multi_onramp.EVM2EVMMultiOnRampTokenTransferFeeConfigArgs{}, ) require.NoErrorf(t, err, "failed to deploy onramp on chain id %d", chainID) backend.Commit() @@ -512,7 +495,7 @@ func connectUniverses( ) { for _, uni := range universes { wireRouter(t, uni, universes) - wireOnRamp(t, uni, universes) + wirePriceRegistry(t, uni, universes) wireOffRamp(t, uni, universes) initRemoteChainsGasPrices(t, uni, universes) } @@ -555,7 +538,7 @@ func setupUniverseBasics(t *testing.T, uni onchainUniverse) { _, err = uni.priceRegistry.UpdatePrices(owner, price_registry.InternalPriceUpdates{ TokenPriceUpdates: tokenPriceUpdates, }) - require.NoErrorf(t, err, "failed to apply price registry updates on chain id %d", uni.chainID) + require.NoErrorf(t, err, "failed to update prices in price registry on chain id %d", uni.chainID) uni.backend.Commit() _, err = uni.priceRegistry.ApplyAuthorizedCallerUpdates(owner, price_registry.AuthorizedCallersAuthorizedCallerArgs{ @@ -609,20 +592,20 @@ func wireRouter(t *testing.T, uni onchainUniverse, universes map[uint64]onchainU } // Setting OnRampDestChainConfigs -func wireOnRamp(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { +func wirePriceRegistry(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { owner := uni.owner - var onrampDestChainConfigArgs []evm_2_evm_multi_onramp.EVM2EVMMultiOnRampDestChainConfigArgs + var priceRegistryDestChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs for remoteChainID := range universes { if remoteChainID == uni.chainID { continue } - onrampDestChainConfigArgs = append(onrampDestChainConfigArgs, evm_2_evm_multi_onramp.EVM2EVMMultiOnRampDestChainConfigArgs{ + priceRegistryDestChainConfigArgs = append(priceRegistryDestChainConfigArgs, price_registry.PriceRegistryDestChainConfigArgs{ DestChainSelector: getSelector(remoteChainID), - DynamicConfig: defaultOnRampDynamicConfig(t), + DestChainConfig: defaultPriceRegistryDestChainConfig(t), }) } - _, err := uni.onramp.ApplyDestChainConfigUpdates(owner, onrampDestChainConfigArgs) - require.NoErrorf(t, err, "failed to apply dest chain config updates on onramp on chain id %d", uni.chainID) + _, err := uni.priceRegistry.ApplyDestChainConfigUpdates(owner, priceRegistryDestChainConfigArgs) + require.NoErrorf(t, err, "failed to apply dest chain config updates on price registry on chain id %d", uni.chainID) uni.backend.Commit() } @@ -673,7 +656,7 @@ func initRemoteChainsGasPrices(t *testing.T, uni onchainUniverse, universes map[ require.NoError(t, err) } -func defaultOnRampDynamicConfig(t *testing.T) evm_2_evm_multi_onramp.EVM2EVMMultiOnRampDestChainDynamicConfig { +func defaultPriceRegistryDestChainConfig(t *testing.T) price_registry.PriceRegistryDestChainConfig { // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 /* ```Solidity @@ -683,7 +666,7 @@ func defaultOnRampDynamicConfig(t *testing.T) evm_2_evm_multi_onramp.EVM2EVMMult */ evmFamilySelector, err := hex.DecodeString("2812d52c") require.NoError(t, err) - return evm_2_evm_multi_onramp.EVM2EVMMultiOnRampDestChainDynamicConfig{ + return price_registry.PriceRegistryDestChainConfig{ IsEnabled: true, MaxNumberOfTokensPerMsg: 10, MaxDataBytes: 256, @@ -748,8 +731,44 @@ func deployRouter(t *testing.T, owner *bind.TransactOpts, backend *backends.Simu return rout } -func deployPriceRegistry(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, linkAddr, wethAddr common.Address, chainID uint64) *price_registry.PriceRegistry { - priceRegistryAddr, _, _, err := price_registry.DeployPriceRegistry(owner, backend, []common.Address{}, []common.Address{linkAddr, wethAddr}, 24*60*60, []price_registry.PriceRegistryTokenPriceFeedUpdate{}) +func deployPriceRegistry( + t *testing.T, + owner *bind.TransactOpts, + backend *backends.SimulatedBackend, + linkAddr, + wethAddr common.Address, + maxFeeJuelsPerMsg *big.Int, + chainID uint64, +) *price_registry.PriceRegistry { + priceRegistryAddr, _, _, err := price_registry.DeployPriceRegistry( + owner, + backend, + price_registry.PriceRegistryStaticConfig{ + MaxFeeJuelsPerMsg: maxFeeJuelsPerMsg, + LinkToken: linkAddr, + StalenessThreshold: 24 * 60 * 60, // 24 hours + }, + []common.Address{ + owner.From, // owner can update prices in this test + }, // price updaters, will be set to offramp later + []common.Address{linkAddr, wethAddr}, // fee tokens + // empty for now, need to fill in when testing token transfers + []price_registry.PriceRegistryTokenPriceFeedUpdate{}, + // empty for now, need to fill in when testing token transfers + []price_registry.PriceRegistryTokenTransferFeeConfigArgs{}, + []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs{ + { + PremiumMultiplierWeiPerEth: 9e17, //0.9 ETH + Token: linkAddr, + }, + { + PremiumMultiplierWeiPerEth: 1e18, + Token: wethAddr, + }, + }, + // Destination chain configs will be set up later once we have all chains + []price_registry.PriceRegistryDestChainConfigArgs{}, + ) require.NoErrorf(t, err, "failed to deploy price registry on chain id %d", chainID) backend.Commit() priceRegistry, err := price_registry.NewPriceRegistry(priceRegistryAddr, backend) diff --git a/core/services/ocr3/plugins/ccip_integration_tests/ocr3_node_test.go b/core/services/ocr3/plugins/ccip_integration_tests/ocr3_node_test.go index 2a7507d7a7..f74be8e563 100644 --- a/core/services/ocr3/plugins/ccip_integration_tests/ocr3_node_test.go +++ b/core/services/ocr3/plugins/ccip_integration_tests/ocr3_node_test.go @@ -141,9 +141,9 @@ func TestIntegration_OCR3Nodes(t *testing.T) { for otherChain, pingPong := range pingPongs[chainID] { t.Log("PingPong From: ", chainID, " To: ", otherChain) - dcc, err1 := uni.onramp.GetDestChainConfig(&bind.CallOpts{}, getSelector(otherChain)) + expNextSeqNr, err1 := uni.onramp.GetExpectedNextSequenceNumber(&bind.CallOpts{}, getSelector(otherChain)) require.NoError(t, err1) - prevSeqNr := dcc.SequenceNumber + require.Equal(t, uint64(1), expNextSeqNr, "expected next sequence number should be 1") uni.backend.Commit() @@ -173,10 +173,12 @@ func TestIntegration_OCR3Nodes(t *testing.T) { paddedAddr := common.LeftPadBytes(chainPingPongAddr, len(log.Message.Receiver)) require.Equal(t, paddedAddr, log.Message.Receiver) - // check that sequence number is bumped in the onramp. - dcc, err = uni.onramp.GetDestChainConfig(&bind.CallOpts{}, log.DestChainSelector) + // check that sequence number is equal to the expected next sequence number. + // and that the sequence number is bumped in the onramp. + require.Equalf(t, log.Message.Header.SequenceNumber, expNextSeqNr, "incorrect sequence number in CCIPSendRequested event on chain %d", log.DestChainSelector) + newExpNextSeqNr, err := uni.onramp.GetExpectedNextSequenceNumber(&bind.CallOpts{}, getSelector(otherChain)) require.NoError(t, err) - require.Equalf(t, dcc.SequenceNumber, prevSeqNr+1, "sequence number not bumped for dest chain selector %d", log.DestChainSelector) + require.Equal(t, expNextSeqNr+1, newExpNextSeqNr, "expected next sequence number should be bumped by 1") _, ok := messageIDs[chainID] if !ok { diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index c1698adeb3..0f0bfd4ab5 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -41,7 +41,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_messenger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" @@ -773,12 +772,12 @@ func (e *CCIPContractsDeployer) NewPriceRegistry(addr common.Address) ( e.logger.Info().Str("Version", version.String()).Msg("New PriceRegistry") switch version { case Latest: - ins, err := price_registry.NewPriceRegistry(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) + ins, err := price_registry_1_2_0.NewPriceRegistry(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) if err != nil { return nil, fmt.Errorf("error in creating price registry instance: %w", err) } wrapper = &PriceRegistryWrapper{ - Latest: ins, + V1_2_0: ins, } case V1_2_0: ins, err := price_registry_1_2_0.NewPriceRegistry(addr, wrappers.MustNewWrappedContractBackend(e.evmClient, nil)) @@ -818,13 +817,13 @@ func (e *CCIPContractsDeployer) DeployPriceRegistry(tokens []common.Address) (*P auth *bind.TransactOpts, _ bind.ContractBackend, ) (common.Address, *types.Transaction, interface{}, error) { - return price_registry.DeployPriceRegistry(auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), nil, tokens, 60*60*24*14, nil) + return price_registry_1_2_0.DeployPriceRegistry(auth, wrappers.MustNewWrappedContractBackend(e.evmClient, nil), nil, tokens, 60*60*24*14) }) if err != nil { return nil, err } wrapper = &PriceRegistryWrapper{ - Latest: instance.(*price_registry.PriceRegistry), + V1_2_0: instance.(*price_registry_1_2_0.PriceRegistry), } case V1_2_0: address, _, instance, err = e.evmClient.DeployContract("PriceRegistry", func( diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 7ab92a673c..290d53c90e 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -102,7 +102,7 @@ var ( LatestPoolVersion = V1_5_0_dev Latest = V1_5_0_dev VersionMap = map[Name]Version{ - PriceRegistryContract: Latest, + PriceRegistryContract: V1_2_0, OffRampContract: Latest, OnRampContract: Latest, CommitStoreContract: Latest,