From 8526467b2f65d4d5d0a28369eda520eb16913d21 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Tue, 21 May 2024 17:12:22 +0200 Subject: [PATCH 01/23] feat: replace ARL with message validation hook on multi-offramp --- .../ccip/interfaces/IMessageValidator.sol | 18 +++++ .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 81 ++++--------------- .../helpers/EVM2EVMMultiOffRampHelper.sol | 6 +- .../test/offRamp/EVM2EVMMultiOffRamp.t.sol | 26 +----- .../offRamp/EVM2EVMMultiOffRampSetup.t.sol | 13 +-- 5 files changed, 41 insertions(+), 103 deletions(-) create mode 100644 contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol diff --git a/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol b/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol new file mode 100644 index 0000000000..c0eff9cc5e --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol @@ -0,0 +1,18 @@ +import {Client} from "../libraries/Client.sol"; + +/// @notice Interface for plug-in message validator contracts that intercept OffRamp & OnRamp messages +/// and perform validations on top of the messages. All validation functions are expected to +/// revert on validation failures. +interface IMessageValidator { + /// @notice The error that is expected to be thrown on validation failures + /// @param errorReason abi encoded revert reason + error MessageValidationFailure(bytes errorReason); + + /// @notice Validates the given OffRamp message. Reverts on validation failure + /// @param message to validate + function validateIncomingMessage(Client.Any2EVMMessage memory message) external view; + + /// @notice Validates the given OnRamp message. Reverts on validation failure + /// @param message to valdidate + function validateOutgoingMessages(Client.EVM2AnyMessage memory message) external view; +} diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 26b78c10ac..7c3701a7fc 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -6,6 +6,8 @@ import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol import {IAny2EVMMultiOffRamp} from "../interfaces/IAny2EVMMultiOffRamp.sol"; import {IAny2EVMOffRamp} from "../interfaces/IAny2EVMOffRamp.sol"; + +import {IMessageValidator} from "../interfaces/IMessageValidator.sol"; import {IMultiCommitStore} from "../interfaces/IMultiCommitStore.sol"; import {IPool} from "../interfaces/IPool.sol"; import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; @@ -14,11 +16,9 @@ import {IRouter} from "../interfaces/IRouter.sol"; import {CallWithExactGas} from "../../shared/call/CallWithExactGas.sol"; import {EnumerableMapAddresses} from "../../shared/enumerable/EnumerableMapAddresses.sol"; -import {AggregateRateLimiter} from "../AggregateRateLimiter.sol"; import {Client} from "../libraries/Client.sol"; import {Internal} from "../libraries/Internal.sol"; import {Pool} from "../libraries/Pool.sol"; -import {RateLimiter} from "../libraries/RateLimiter.sol"; import {OCR2BaseNoChecks} from "../ocr/OCR2BaseNoChecks.sol"; import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; @@ -30,7 +30,7 @@ import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts /// @dev OCR2BaseNoChecks is used to save gas, signatures are not required as the offramp can only execute /// messages which are committed in the commitStore. We still make use of OCR2 as an executor whitelist /// and turn-taking mechanism. -contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITypeAndVersion, OCR2BaseNoChecks { +contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseNoChecks { using ERC165Checker for address; using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; @@ -71,8 +71,6 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp Internal.MessageExecutionState state, bytes returnData ); - event TokenAggregateRateLimitAdded(address sourceToken, address destToken); - event TokenAggregateRateLimitRemoved(address sourceToken, address destToken); event SourceChainSelectorAdded(uint64 sourceChainSelector); event SourceChainConfigSet(uint64 indexed sourceChainSelector, SourceChainConfig sourceConfig); event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 sequenceNumber); @@ -115,12 +113,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp uint16 maxNumberOfTokensPerMsg; // │ Maximum number of ERC20 token transfers that can be included per message uint32 maxDataBytes; // │ Maximum payload data size in bytes uint32 maxPoolReleaseOrMintGas; // ─╯ Maximum amount of gas passed on to token pool when calling releaseOrMint - } - - /// @notice RateLimitToken struct containing both the source and destination token addresses - struct RateLimitToken { - address sourceToken; - address destToken; + address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) } /// @notice Struct that represents a message route (sender -> receiver and source chain) @@ -141,9 +134,6 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp // DYNAMIC CONFIG DynamicConfig internal s_dynamicConfig; - /// @dev Tokens that should be included in Aggregate Rate Limiting - /// An (address => address) map is used for backwards compatability of offchain code - EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensDestToSource; // TODO: evaluate whether this should be pulled in (since this can be inferred from SourceChainSelectorAdded events instead) /// @notice all source chains available in s_sourceChainConfigs @@ -165,12 +155,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp mapping(uint64 sourceChainSelector => mapping(uint64 seqNum => uint256 executionStateBitmap)) internal s_executionStates; - constructor( - StaticConfig memory staticConfig, - SourceChainConfigArgs[] memory sourceChainConfigs, - // TODO: remove and convert to generic hook on message sending - RateLimiter.Config memory rateLimiterConfig - ) OCR2BaseNoChecks() AggregateRateLimiter(rateLimiterConfig) { + constructor(StaticConfig memory staticConfig, SourceChainConfigArgs[] memory sourceChainConfigs) OCR2BaseNoChecks() { if (staticConfig.commitStore == address(0)) revert ZeroAddressNotAllowed(); i_commitStore = staticConfig.commitStore; @@ -492,6 +477,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp uint256 dataLength, uint256 offchainTokenDataLength ) private view { + // TODO: move maxNumberOfTokens & data lnegth validation offchain if (numberOfTokens > uint256(s_dynamicConfig.maxNumberOfTokensPerMsg)) { revert UnsupportedNumberOfTokens(sourceChainSelector, sequenceNumber); } @@ -516,6 +502,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp ReceiverError.selector == bytes4(err) || TokenHandlingError.selector == bytes4(err) || Internal.InvalidEVMAddress.selector == bytes4(err) || InvalidDataLength.selector == bytes4(err) || CallWithExactGas.NoContract.selector == bytes4(err) || NotACompatiblePool.selector == bytes4(err) + || IMessageValidator.MessageValidationFailure.selector == bytes4(err) ) { // If CCIP receiver execution is not successful, bubble up receiver revert data, // prepended by the 4 bytes of ReceiverError.selector, TokenHandlingError.selector or InvalidPoolAddress.selector. @@ -566,11 +553,15 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) ) return; + Client.Any2EVMMessage memory any2EvmMessage = Internal._toAny2EVMMessage(message, destTokenAmounts); + + address messageValidator = s_dynamicConfig.messageValidator; + if (messageValidator != address(0)) { + IMessageValidator(messageValidator).validateIncomingMessage(any2EvmMessage); + } + (bool success, bytes memory returnData,) = IRouter(s_dynamicConfig.router).routeMessage( - Internal._toAny2EVMMessage(message, destTokenAmounts), - Internal.GAS_FOR_CALL_EXACT_CHECK, - message.gasLimit, - message.receiver + any2EvmMessage, Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver ); // If CCIP receiver execution is not successful, revert the call including token transfers if (!success) revert ReceiverError(returnData); @@ -679,41 +670,6 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp ); } - // TODO: move the 2 rate limit functions to the ARL hook contract - /// @notice Get all tokens which are included in Aggregate Rate Limiting. - /// @return sourceTokens The source representation of the tokens that are rate limited. - /// @return destTokens The destination representation of the tokens that are rate limited. - /// @dev the order of IDs in the list is **not guaranteed**, therefore, if ordering matters when - /// making successive calls, one should keep the blockheight constant to ensure a consistent result. - function getAllRateLimitTokens() external view returns (address[] memory sourceTokens, address[] memory destTokens) { - sourceTokens = new address[](s_rateLimitedTokensDestToSource.length()); - destTokens = new address[](s_rateLimitedTokensDestToSource.length()); - - for (uint256 i = 0; i < s_rateLimitedTokensDestToSource.length(); ++i) { - (address destToken, address sourceToken) = s_rateLimitedTokensDestToSource.at(i); - sourceTokens[i] = sourceToken; - destTokens[i] = destToken; - } - return (sourceTokens, destTokens); - } - - /// @notice Adds or removes tokens from being used in Aggregate Rate Limiting. - /// @param removes - A list of one or more tokens to be removed. - /// @param adds - A list of one or more tokens to be added. - function updateRateLimitTokens(RateLimitToken[] memory removes, RateLimitToken[] memory adds) external onlyOwner { - for (uint256 i = 0; i < removes.length; ++i) { - if (s_rateLimitedTokensDestToSource.remove(removes[i].destToken)) { - emit TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); - } - } - - for (uint256 i = 0; i < adds.length; ++i) { - if (s_rateLimitedTokensDestToSource.set(adds[i].destToken, adds[i].sourceToken)) { - emit TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); - } - } - } - // ================================================================ // │ Tokens and pools │ // ================================================================ @@ -734,7 +690,6 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { // Creating a copy is more gas efficient than initializing a new array. destTokenAmounts = sourceTokenAmounts; - uint256 value = 0; for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { // This should never revert as the onRamp creates the sourceTokenData. Only the inner components from // this struct come from untrusted sources. @@ -785,14 +740,8 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, AggregateRateLimiter, ITyp (uint256 decodedAddress, uint256 amount) = abi.decode(returnData, (uint256, uint256)); destTokenAmounts[i].token = Internal._validateEVMAddressFromUint256(decodedAddress); destTokenAmounts[i].amount = amount; - - if (s_rateLimitedTokensDestToSource.contains(destTokenAmounts[i].token)) { - value += _getTokenValue(destTokenAmounts[i], IPriceRegistry(s_dynamicConfig.priceRegistry)); - } } - if (value > 0) _rateLimitValue(value); - return destTokenAmounts; } diff --git a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol index a9e639f7f3..ca238c6203 100644 --- a/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/EVM2EVMMultiOffRampHelper.sol @@ -3,16 +3,14 @@ pragma solidity 0.8.24; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {EVM2EVMMultiOffRamp} from "../../offRamp/EVM2EVMMultiOffRamp.sol"; import {IgnoreContractSize} from "./IgnoreContractSize.sol"; contract EVM2EVMMultiOffRampHelper is EVM2EVMMultiOffRamp, IgnoreContractSize { constructor( StaticConfig memory staticConfig, - SourceChainConfigArgs[] memory sourceChainConfigs, - RateLimiter.Config memory rateLimiterConfig - ) EVM2EVMMultiOffRamp(staticConfig, sourceChainConfigs, rateLimiterConfig) {} + SourceChainConfigArgs[] memory sourceChainConfigs + ) EVM2EVMMultiOffRamp(staticConfig, sourceChainConfigs) {} function setExecutionStateHelper( uint64 sourceChainSelector, diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index d8f3132179..00fc3b0351 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -6,7 +6,6 @@ import {IMultiCommitStore} from "../../interfaces/IMultiCommitStore.sol"; import {IPool} from "../../interfaces/IPool.sol"; import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; -import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol"; import {RMN} from "../../RMN.sol"; import {Router} from "../../Router.sol"; import {Client} from "../../libraries/Client.sol"; @@ -88,7 +87,7 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { vm.expectEmit(); emit SourceChainConfigSet(SOURCE_CHAIN_SELECTOR_1 + 1, expectedSourceChainConfig2); - s_offRamp = new EVM2EVMMultiOffRampHelper(staticConfig, sourceChainConfigs, getInboundRateLimiterConfig()); + s_offRamp = new EVM2EVMMultiOffRampHelper(staticConfig, sourceChainConfigs); s_offRamp.setOCR2Config( s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") @@ -145,8 +144,7 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { chainSelector: DEST_CHAIN_SELECTOR, rmnProxy: address(s_mockRMN) }), - sourceChainConfigs, - RateLimiter.Config({isEnabled: true, rate: 1e20, capacity: 1e20}) + sourceChainConfigs ); } } @@ -264,7 +262,7 @@ contract EVM2EVMMultiOffRamp_metadataHash is EVM2EVMMultiOffRampSetup { new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](0); staticConfig.chainSelector = destChainSelector; - s_offRamp = new EVM2EVMMultiOffRampHelper(staticConfig, sourceChainConfigs, getInboundRateLimiterConfig()); + s_offRamp = new EVM2EVMMultiOffRampHelper(staticConfig, sourceChainConfigs); bytes32 h1 = s_offRamp.metadataHash(sourceChainSelector1, onRamp1); bytes32 h2 = s_offRamp.metadataHash(sourceChainSelector2, onRamp2); @@ -2473,24 +2471,6 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { s_offRamp.releaseOrMintTokens(srcTokenAmounts, messageRouteChain3, encodedSourceTokenData, offchainTokenData); } - function test_PriceNotFoundForToken_Reverts() public { - // Set token price to 0 - s_priceRegistry.updatePrices(getSingleTokenPriceUpdateStruct(s_destFeeToken, 0)); - - Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - uint256 amount1 = 100; - srcTokenAmounts[0].amount = amount1; - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - offchainTokenData[0] = abi.encode(0x12345678); - - bytes[] memory sourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - - vm.expectRevert(abi.encodeWithSelector(AggregateRateLimiter.PriceNotFoundForToken.selector, s_destFeeToken)); - - s_offRamp.releaseOrMintTokens(srcTokenAmounts, MESSAGE_ROUTE, sourceTokenData, offchainTokenData); - } - /// forge-config: default.fuzz.runs = 32 /// forge-config: ccip.fuzz.runs = 1024 // Uint256 gives a good range of values to test, both inside and outside of the eth address space. diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol index c27a6aab30..d6f9120b50 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol @@ -77,8 +77,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet chainSelector: DEST_CHAIN_SELECTOR, rmnProxy: address(s_mockRMN) }), - sourceChainConfigs, - getInboundRateLimiterConfig() + sourceChainConfigs ); s_offRamp.setOCR2Config( s_valid_signers, @@ -88,13 +87,6 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet s_offchainConfigVersion, abi.encode("") ); - - EVM2EVMMultiOffRamp.RateLimitToken[] memory tokensToAdd = - new EVM2EVMMultiOffRamp.RateLimitToken[](s_sourceTokens.length); - for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - tokensToAdd[i] = EVM2EVMMultiOffRamp.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); - } - s_offRamp.updateRateLimitTokens(new EVM2EVMMultiOffRamp.RateLimitToken[](0), tokensToAdd); } // TODO: function can be made common across OffRampSetup and MultiOffRampSetup @@ -222,7 +214,8 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet priceRegistry: priceRegistry, maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, maxDataBytes: MAX_DATA_SIZE, - maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS + maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, + messageValidator: address(0) }); } From 5499569e7dbf01d24ec7c1582106f675a269c92d Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Tue, 21 May 2024 17:26:15 +0200 Subject: [PATCH 02/23] feat: create multi-arl contract --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 97 ++-- .../ccip/libraries/RateLimiterNoEvents.sol | 152 +++++++ .../MultiAggregateRateLimiterHelper.sol | 24 + .../helpers/RateLimiterNoEventsHelper.sol | 36 ++ .../test/libraries/RateLimiterNoEvents.t.sol | 297 +++++++++++++ .../MultiAggregateRateLimiter.t.sol | 420 +++++++++++------- 6 files changed, 842 insertions(+), 184 deletions(-) create mode 100644 contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol create mode 100644 contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol create mode 100644 contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol create mode 100644 contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 4d79ea5c58..eba1130a4d 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -5,41 +5,49 @@ import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; import {Client} from "./libraries/Client.sol"; -import {RateLimiter} from "./libraries/RateLimiter.sol"; +import {RateLimiterNoEvents} from "./libraries/RateLimiterNoEvents.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of /// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). contract MultiAggregateRateLimiter is OwnerIsCreator { - using RateLimiter for RateLimiter.TokenBucket; + using RateLimiterNoEvents for RateLimiterNoEvents.TokenBucket; using USDPriceWith18Decimals for uint224; error PriceNotFoundForToken(address token); + error UpdateLengthMismatch(); + event RateLimiterConfigUpdated(uint64 indexed chainSelector, RateLimiterNoEvents.Config config); + event RateLimiterTokensConsumed(uint64 indexed chainSelector, uint256 tokens); event AdminSet(address newAdmin); // The address of the token limit admin that has the same permissions as the owner. address internal s_admin; - // The token bucket object that contains the bucket state. - RateLimiter.TokenBucket private s_rateLimiter; - - /// @param config The RateLimiter.Config containing the capacity and refill rate - /// of the bucket, plus the admin address. - constructor(RateLimiter.Config memory config) { - s_rateLimiter = RateLimiter.TokenBucket({ - rate: config.rate, - capacity: config.capacity, - tokens: config.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: config.isEnabled - }); + // Rate limiter token bucket states per chain + mapping(uint64 chainSelector => RateLimiterNoEvents.TokenBucket rateLimiter) s_rateLimitersByChainSelector; + + /// @notice A collection of rate limiter configuration updates + struct RateLimiterConfigUpdates { + uint64[] chainSelectors; + RateLimiterNoEvents.Config[] rateLimiterConfigs; + } + + /// @param rateLimiterConfigs The RateLimiterNoEvents.Configs per chain containing the capacity and refill rate + /// of the bucket + /// @param admin the admin address to set + constructor(RateLimiterConfigUpdates memory rateLimiterConfigs, address admin) { + _applyRateLimiterConfigUpdates(rateLimiterConfigs); + _setAdmin(admin); } /// @notice Consumes value from the rate limiter bucket based on the token value given. - function _rateLimitValue(uint256 value) internal { - s_rateLimiter._consume(value, address(0)); + /// @param chainSelector chain selector to apply rate limit to + /// @param value consumed value + function _rateLimitValue(uint64 chainSelector, uint256 value) internal { + s_rateLimitersByChainSelector[chainSelector]._consume(value, address(0)); + emit RateLimiterTokensConsumed(chainSelector, value); } function _getTokenValue( @@ -54,16 +62,48 @@ contract MultiAggregateRateLimiter is OwnerIsCreator { } /// @notice Gets the token bucket with its values for the block it was requested at. + /// @param chainSelector chain selector to retrieve state for /// @return The token bucket. - function currentRateLimiterState() external view returns (RateLimiter.TokenBucket memory) { - return s_rateLimiter._currentTokenBucketState(); + function currentRateLimiterState(uint64 chainSelector) external view returns (RateLimiterNoEvents.TokenBucket memory) { + return s_rateLimitersByChainSelector[chainSelector]._currentTokenBucketState(); + } + + /// @notice Applies the provided rate limiter config updates. + /// @param rateLimiterUpdates Rate limiter updates + /// @dev should only be callable by the owner or token limit admin + function applyRateLimiterConfigUpdates(RateLimiterConfigUpdates memory rateLimiterUpdates) external onlyAdminOrOwner { + _applyRateLimiterConfigUpdates(rateLimiterUpdates); } - /// @notice Sets the rate limited config. - /// @param config The new rate limiter config. - /// @dev should only be callable by the owner or token limit admin. - function setRateLimiterConfig(RateLimiter.Config memory config) external onlyAdminOrOwner { - s_rateLimiter._setTokenBucketConfig(config); + /// @notice Applies the provided rate limiter config updates. + /// @param rateLimiterUpdates Rate limiter updates + function _applyRateLimiterConfigUpdates(RateLimiterConfigUpdates memory rateLimiterUpdates) internal { + uint256 updateLength = rateLimiterUpdates.chainSelectors.length; + if (updateLength != rateLimiterUpdates.rateLimiterConfigs.length) { + revert UpdateLengthMismatch(); + } + + for (uint256 i = 0; i < updateLength; ++i) { + RateLimiterNoEvents.Config memory configUpdate = rateLimiterUpdates.rateLimiterConfigs[i]; + uint64 chainSelector = rateLimiterUpdates.chainSelectors[i]; + + RateLimiterNoEvents.TokenBucket memory tokenBucket = s_rateLimitersByChainSelector[chainSelector]; + uint32 lastUpdated = tokenBucket.lastUpdated; + + if (lastUpdated == 0) { + // Token bucket needs to be newly added + s_rateLimitersByChainSelector[chainSelector] = RateLimiterNoEvents.TokenBucket({ + rate: configUpdate.rate, + capacity: configUpdate.capacity, + tokens: configUpdate.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: configUpdate.isEnabled + }); + } else { + s_rateLimitersByChainSelector[chainSelector]._setTokenBucketConfig(configUpdate); + } + emit RateLimiterConfigUpdated(chainSelector, configUpdate); + } } // ================================================================ @@ -80,6 +120,13 @@ contract MultiAggregateRateLimiter is OwnerIsCreator { /// @param newAdmin the address of the new admin. /// @dev setting this to address(0) indicates there is no active admin. function setAdmin(address newAdmin) external onlyAdminOrOwner { + _setAdmin(newAdmin); + } + + /// @notice Sets the token limit admin address. + /// @param newAdmin the address of the new admin. + /// @dev setting this to address(0) indicates there is no active admin. + function _setAdmin(address newAdmin) internal { s_admin = newAdmin; emit AdminSet(newAdmin); } @@ -87,7 +134,7 @@ contract MultiAggregateRateLimiter is OwnerIsCreator { /// @notice a modifier that allows the owner or the s_tokenLimitAdmin call the functions /// it is applied to. modifier onlyAdminOrOwner() { - if (msg.sender != owner() && msg.sender != s_admin) revert RateLimiter.OnlyCallableByAdminOrOwner(); + if (msg.sender != owner() && msg.sender != s_admin) revert RateLimiterNoEvents.OnlyCallableByAdminOrOwner(); _; } } diff --git a/contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol b/contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol new file mode 100644 index 0000000000..baaaf4a63a --- /dev/null +++ b/contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +/// @notice Implements Token Bucket rate limiting. +/// @dev uint128 is safe for rate limiter state. +/// For USD value rate limiting, it can adequately store USD value in 18 decimals. +/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most +/// a supply of uint128.max tokens, and it will therefore not overflow the bucket. +/// In exceptional scenarios where tokens consumed may be larger than uint128, +/// e.g. compromised issuer, an enabled RateLimiter will check and revert. +/// This version of the RateLimiter delegates event emissions to the consumer. +library RateLimiterNoEvents { + error BucketOverfilled(); + error OnlyCallableByAdminOrOwner(); + error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); + error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); + error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); + error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); + error InvalidRatelimitRate(Config rateLimiterConfig); + error DisabledNonZeroRateLimit(Config config); + error RateLimitMustBeDisabled(); + + struct TokenBucket { + uint128 tokens; // ──────╮ Current number of tokens that are in the bucket. + uint32 lastUpdated; // │ Timestamp in seconds of the last token refill, good for 100+ years. + bool isEnabled; // ──────╯ Indication whether the rate limiting is enabled or not + uint128 capacity; // ────╮ Maximum number of tokens that can be in the bucket. + uint128 rate; // ────────╯ Number of tokens per second that the bucket is refilled. + } + + struct Config { + bool isEnabled; // Indication whether the rate limiting should be enabled + uint128 capacity; // ────╮ Specifies the capacity of the rate limiter + uint128 rate; // ───────╯ Specifies the rate of the rate limiter + } + + /// @notice _consume removes the given tokens from the pool, lowering the + /// rate tokens allowed to be consumed for subsequent calls. + /// @param requestTokens The total tokens to be consumed from the bucket. + /// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity. + /// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket + /// @dev emits removal of requestTokens if requestTokens is > 0 + function _consume(TokenBucket storage s_bucket, uint256 requestTokens, address tokenAddress) internal { + // If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage + if (!s_bucket.isEnabled || requestTokens == 0) { + return; + } + + uint256 tokens = s_bucket.tokens; + uint256 capacity = s_bucket.capacity; + uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; + + if (timeDiff != 0) { + if (tokens > capacity) revert BucketOverfilled(); + + // Refill tokens when arriving at a new block time + tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate); + + s_bucket.lastUpdated = uint32(block.timestamp); + } + + if (capacity < requestTokens) { + // Token address 0 indicates consuming aggregate value rate limit capacity. + if (tokenAddress == address(0)) revert AggregateValueMaxCapacityExceeded(capacity, requestTokens); + revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress); + } + if (tokens < requestTokens) { + uint256 rate = s_bucket.rate; + // Wait required until the bucket is refilled enough to accept this value, round up to next higher second + // Consume is not guaranteed to succeed after wait time passes if there is competing traffic. + // This acts as a lower bound of wait time. + uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate; + + if (tokenAddress == address(0)) revert AggregateValueRateLimitReached(minWaitInSeconds, tokens); + revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress); + } + tokens -= requestTokens; + + // Downcast is safe here, as tokens is not larger than capacity + s_bucket.tokens = uint128(tokens); + } + + /// @notice Gets the token bucket with its values for the block it was requested at. + /// @return The token bucket. + function _currentTokenBucketState(TokenBucket memory bucket) internal view returns (TokenBucket memory) { + // We update the bucket to reflect the status at the exact time of the + // call. This means we might need to refill a part of the bucket based + // on the time that has passed since the last update. + bucket.tokens = + uint128(_calculateRefill(bucket.capacity, bucket.tokens, block.timestamp - bucket.lastUpdated, bucket.rate)); + bucket.lastUpdated = uint32(block.timestamp); + return bucket; + } + + /// @notice Sets the rate limited config. + /// @param s_bucket The token bucket + /// @param config The new config + function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal { + // First update the bucket to make sure the proper rate is used for all the time + // up until the config change. + uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; + if (timeDiff != 0) { + s_bucket.tokens = uint128(_calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate)); + + s_bucket.lastUpdated = uint32(block.timestamp); + } + + s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens)); + s_bucket.isEnabled = config.isEnabled; + s_bucket.capacity = config.capacity; + s_bucket.rate = config.rate; + } + + /// @notice Validates the token bucket config + function _validateTokenBucketConfig(Config memory config, bool mustBeDisabled) internal pure { + if (config.isEnabled) { + if (config.rate >= config.capacity || config.rate == 0) { + revert InvalidRatelimitRate(config); + } + if (mustBeDisabled) { + revert RateLimitMustBeDisabled(); + } + } else { + if (config.rate != 0 || config.capacity != 0) { + revert DisabledNonZeroRateLimit(config); + } + } + } + + /// @notice Calculate refilled tokens + /// @param capacity bucket capacity + /// @param tokens current bucket tokens + /// @param timeDiff block time difference since last refill + /// @param rate bucket refill rate + /// @return the value of tokens after refill + function _calculateRefill( + uint256 capacity, + uint256 tokens, + uint256 timeDiff, + uint256 rate + ) private pure returns (uint256) { + return _min(capacity, tokens + timeDiff * rate); + } + + /// @notice Return the smallest of two integers + /// @param a first int + /// @param b second int + /// @return smallest + function _min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol new file mode 100644 index 0000000000..f70b7ba2f0 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; +import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; +import {Client} from "../../libraries/Client.sol"; + +contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { + constructor( + MultiAggregateRateLimiter.RateLimiterConfigUpdates memory rateLimiterConfigs, + address admin + ) MultiAggregateRateLimiter(rateLimiterConfigs, admin) {} + + function rateLimitValue(uint64 chainSelector, uint256 value) public { + _rateLimitValue(chainSelector, value); + } + + function getTokenValue( + Client.EVMTokenAmount memory tokenAmount, + IPriceRegistry priceRegistry + ) public view returns (uint256) { + return _getTokenValue(tokenAmount, priceRegistry); + } +} diff --git a/contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol b/contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol new file mode 100644 index 0000000000..b8dbff9f30 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; + +contract RateLimiterNoEventsHelper { + using RateLimiterNoEvents for RateLimiterNoEvents.TokenBucket; + + RateLimiterNoEvents.TokenBucket internal s_rateLimiter; + + constructor(RateLimiterNoEvents.Config memory config) { + s_rateLimiter = RateLimiterNoEvents.TokenBucket({ + rate: config.rate, + capacity: config.capacity, + tokens: config.capacity, + lastUpdated: uint32(block.timestamp), + isEnabled: config.isEnabled + }); + } + + function consume(uint256 requestTokens, address tokenAddress) external { + s_rateLimiter._consume(requestTokens, tokenAddress); + } + + function currentTokenBucketState() external view returns (RateLimiterNoEvents.TokenBucket memory) { + return s_rateLimiter._currentTokenBucketState(); + } + + function setTokenBucketConfig(RateLimiterNoEvents.Config memory config) external { + s_rateLimiter._setTokenBucketConfig(config); + } + + function getRateLimiter() external view returns (RateLimiterNoEvents.TokenBucket memory) { + return s_rateLimiter; + } +} diff --git a/contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol b/contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol new file mode 100644 index 0000000000..a3cb1c896a --- /dev/null +++ b/contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol @@ -0,0 +1,297 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {RateLimiterNoEventsHelper} from "../helpers/RateLimiterNoEventsHelper.sol"; + +contract RateLimiterNoEventsSetup is BaseTest { + RateLimiterNoEventsHelper internal s_helper; + RateLimiterNoEvents.Config internal s_config; + + function setUp() public virtual override { + BaseTest.setUp(); + + s_config = RateLimiterNoEvents.Config({isEnabled: true, rate: 5, capacity: 100}); + s_helper = new RateLimiterNoEventsHelper(s_config); + } +} + +contract RateLimiterNoEvents_constructor is RateLimiterNoEventsSetup { + function test_Constructor_Success() public view { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + } +} + +/// @notice #setTokenBucketConfig +contract RateLimiterNoEvents_setTokenBucketConfig is RateLimiterNoEventsSetup { + function test_SetRateLimiterNoEventsConfig_Success() public { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + + s_config = RateLimiterNoEvents.Config({ + isEnabled: true, + rate: uint128(rateLimiter.rate * 2), + capacity: rateLimiter.capacity * 8 + }); + + s_helper.setTokenBucketConfig(s_config); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity / 8, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + } +} + +/// @notice #currentTokenBucketState +contract RateLimiterNoEvents_currentTokenBucketState is RateLimiterNoEventsSetup { + function test_CurrentTokenBucketState_Success() public { + RateLimiterNoEvents.TokenBucket memory bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + + s_config = + RateLimiterNoEvents.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); + + s_helper.setTokenBucketConfig(s_config); + + bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity / 8, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + } + + function test_Refill_Success() public { + RateLimiterNoEvents.TokenBucket memory bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + + s_config = + RateLimiterNoEvents.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); + + s_helper.setTokenBucketConfig(s_config); + + bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.rate, bucket.rate); + assertEq(s_config.capacity, bucket.capacity); + assertEq(s_config.capacity / 8, bucket.tokens); + assertEq(s_config.isEnabled, bucket.isEnabled); + assertEq(BLOCK_TIME, bucket.lastUpdated); + + uint256 warpTime = 4; + vm.warp(BLOCK_TIME + warpTime); + + bucket = s_helper.currentTokenBucketState(); + + assertEq(s_config.capacity / 8 + warpTime * s_config.rate, bucket.tokens); + + vm.warp(BLOCK_TIME + warpTime * 100); + + // Bucket overflow + bucket = s_helper.currentTokenBucketState(); + assertEq(s_config.capacity, bucket.tokens); + } +} + +/// @notice #consume +contract RateLimiterNoEvents_consume is RateLimiterNoEventsSetup { + address internal s_token = address(100); + + function test_ConsumeAggregateValue_Success() public { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + + uint256 requestTokens = 50; + + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + } + + function test_ConsumeTokens_Success() public { + uint256 requestTokens = 50; + + s_helper.consume(requestTokens, s_token); + } + + function test_Refill_Success() public { + uint256 requestTokens = 50; + + s_helper.consume(requestTokens, address(0)); + + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME, rateLimiter.lastUpdated); + + uint256 warpTime = 4; + vm.warp(BLOCK_TIME + warpTime); + + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(s_config.capacity - requestTokens * 2 + warpTime * s_config.rate, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + assertEq(BLOCK_TIME + warpTime, rateLimiter.lastUpdated); + } + + function test_ConsumeUnlimited_Success() public { + s_helper.consume(0, address(0)); + + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.capacity, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + + RateLimiterNoEvents.Config memory disableConfig = + RateLimiterNoEvents.Config({isEnabled: false, rate: 0, capacity: 0}); + + s_helper.setTokenBucketConfig(disableConfig); + + uint256 requestTokens = 50; + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(disableConfig.capacity, rateLimiter.tokens); + assertEq(disableConfig.isEnabled, rateLimiter.isEnabled); + + s_helper.setTokenBucketConfig(s_config); + + vm.expectRevert(abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 10, 0)); + s_helper.consume(requestTokens, address(0)); + + rateLimiter = s_helper.getRateLimiter(); + assertEq(s_config.rate, rateLimiter.rate); + assertEq(s_config.capacity, rateLimiter.capacity); + assertEq(0, rateLimiter.tokens); + assertEq(s_config.isEnabled, rateLimiter.isEnabled); + } + + // Reverts + + function test_AggregateValueMaxCapacityExceeded_Revert() public { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1 + ) + ); + s_helper.consume(rateLimiter.capacity + 1, address(0)); + } + + function test_TokenMaxCapacityExceeded_Revert() public { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiterNoEvents.TokenMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1, s_token + ) + ); + s_helper.consume(rateLimiter.capacity + 1, s_token); + } + + function test_ConsumingMoreThanUint128_Revert() public { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + uint256 request = uint256(type(uint128).max) + 1; + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, request + ) + ); + s_helper.consume(request, address(0)); + } + + function test_AggregateValueRateLimitReached_Revert() public { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + uint256 overLimit = 20; + uint256 requestTokens1 = rateLimiter.capacity / 2; + uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; + + uint256 waitInSeconds = overLimit / rateLimiter.rate; + + s_helper.consume(requestTokens1, address(0)); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiterNoEvents.AggregateValueRateLimitReached.selector, + waitInSeconds, + rateLimiter.capacity - requestTokens1 + ) + ); + s_helper.consume(requestTokens2, address(0)); + } + + function test_TokenRateLimitReached_Revert() public { + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + uint256 overLimit = 20; + uint256 requestTokens1 = rateLimiter.capacity / 2; + uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; + + uint256 waitInSeconds = overLimit / rateLimiter.rate; + + s_helper.consume(requestTokens1, s_token); + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiterNoEvents.TokenRateLimitReached.selector, + waitInSeconds, + rateLimiter.capacity - requestTokens1, + s_token + ) + ); + s_helper.consume(requestTokens2, s_token); + } + + function test_RateLimitReachedOverConsecutiveBlocks_Revert() public { + uint256 initBlockTime = BLOCK_TIME + 10000; + vm.warp(initBlockTime); + + RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); + + s_helper.consume(rateLimiter.capacity, address(0)); + + vm.warp(initBlockTime + 1); + + // Over rate limit by 1, force 1 second wait + uint256 overLimit = 1; + + vm.expectRevert( + abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 1, rateLimiter.rate) + ); + s_helper.consume(rateLimiter.rate + overLimit, address(0)); + } +} diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index dce3bfe20b..7f79ce6b1b 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -1,46 +1,136 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol"; +import {Vm} from "forge-std/Vm.sol"; + +import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {RateLimiter} from "../../libraries/RateLimiter.sol"; -import {AggregateRateLimiterHelper} from "../helpers/AggregateRateLimiterHelper.sol"; +import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {MultiAggregateRateLimiterHelper} from "../helpers/MultiAggregateRateLimiterHelper.sol"; import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; import {stdError} from "forge-std/Test.sol"; -contract MultiAggregateRateLimiterSetup is PriceRegistrySetup { - AggregateRateLimiterHelper internal s_rateLimiter; - RateLimiter.Config internal s_config; +contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { + MultiAggregateRateLimiterHelper internal s_rateLimiter; address internal immutable TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; uint224 internal constant TOKEN_PRICE = 4e18; - function setUp() public virtual override { + uint64 internal constant SRC_CHAIN_1_SELECTOR = 5009297550715157269; + RateLimiterNoEvents.Config internal SRC_CHAIN_1_RATE_LIMITER_CONFIG = + RateLimiterNoEvents.Config({isEnabled: true, rate: 5, capacity: 100}); + uint64 internal constant SRC_CHAIN_2_SELECTOR = 4949039107694359620; + RateLimiterNoEvents.Config internal SRC_CHAIN_2_RATE_LIMITER_CONFIG = + RateLimiterNoEvents.Config({isEnabled: true, rate: 10, capacity: 200}); + + function setUp() public virtual override(BaseTest, PriceRegistrySetup) { + BaseTest.setUp(); PriceRegistrySetup.setUp(); Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); s_priceRegistry.updatePrices(priceUpdates); - s_config = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); - s_rateLimiter = new AggregateRateLimiterHelper(s_config); - s_rateLimiter.setAdmin(ADMIN); + RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](2); + rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; + rateLimiterConfigs[1] = SRC_CHAIN_2_RATE_LIMITER_CONFIG; + + uint64[] memory chainSelectors = new uint64[](2); + chainSelectors[0] = SRC_CHAIN_1_SELECTOR; + chainSelectors[1] = SRC_CHAIN_2_SELECTOR; + + MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter + .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); } } /// @notice #constructor contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup { - function test_Constructor_Success() public view { + event RateLimiterConfigUpdated(uint64 indexed chainSelector, RateLimiterNoEvents.Config config); + + function test_ConstructorNoConfigs_Success() public { + RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](0); + uint64[] memory chainSelectors = new uint64[](0); + + MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter + .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + + vm.recordLogs(); + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); + + // Single log for AdminSet + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); + } + + function test_ConstructorSingleConfig_Success() public { + RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](1); + rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; + + uint64[] memory chainSelectors = new uint64[](1); + chainSelectors[0] = SRC_CHAIN_1_SELECTOR; + + MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter + .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + + vm.expectEmit(); + emit RateLimiterConfigUpdated(SRC_CHAIN_1_SELECTOR, SRC_CHAIN_1_RATE_LIMITER_CONFIG); + + vm.recordLogs(); + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); + + // Log for AdminSet + RateLimiterConfigSet + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 2); + + RateLimiterNoEvents.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucketSrcChain1.rate); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.capacity); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.tokens); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.isEnabled, bucketSrcChain1.isEnabled); + assertEq(BLOCK_TIME, bucketSrcChain1.lastUpdated); + } + + function test_ConstructorMultipleConfigs_Success() public { + RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](2); + rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; + rateLimiterConfigs[1] = SRC_CHAIN_2_RATE_LIMITER_CONFIG; + + uint64[] memory chainSelectors = new uint64[](2); + chainSelectors[0] = SRC_CHAIN_1_SELECTOR; + chainSelectors[1] = SRC_CHAIN_2_SELECTOR; + + MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter + .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + + vm.expectEmit(); + emit RateLimiterConfigUpdated(SRC_CHAIN_1_SELECTOR, SRC_CHAIN_1_RATE_LIMITER_CONFIG); + + vm.expectEmit(); + emit RateLimiterConfigUpdated(SRC_CHAIN_2_SELECTOR, SRC_CHAIN_2_RATE_LIMITER_CONFIG); + + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); + assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); assertEq(OWNER, s_rateLimiter.owner()); - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); + RateLimiterNoEvents.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucketSrcChain1.rate); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.capacity); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.tokens); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.isEnabled, bucketSrcChain1.isEnabled); + assertEq(BLOCK_TIME, bucketSrcChain1.lastUpdated); + + RateLimiterNoEvents.TokenBucket memory bucketSrcChain2 = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_2_SELECTOR); + assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.rate, bucketSrcChain2.rate); + assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.capacity, bucketSrcChain2.capacity); + assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.capacity, bucketSrcChain2.tokens); + assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.isEnabled, bucketSrcChain2.isEnabled); + assertEq(BLOCK_TIME, bucketSrcChain2.lastUpdated); } } @@ -67,7 +157,7 @@ contract MultiAggregateRateLimiter_setAdmin is MultiAggregateRateLimiterSetup { function test_OnlyOwnerOrAdmin_Revert() public { vm.startPrank(STRANGER); - vm.expectRevert(RateLimiter.OnlyCallableByAdminOrOwner.selector); + vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); s_rateLimiter.setAdmin(STRANGER); } @@ -76,39 +166,51 @@ contract MultiAggregateRateLimiter_setAdmin is MultiAggregateRateLimiterSetup { /// @notice #getTokenBucket contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { function test_GetTokenBucket_Success() public view { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); + RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.rate); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.capacity); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.tokens); assertEq(BLOCK_TIME, bucket.lastUpdated); } function test_Refill_Success() public { - s_config.capacity = s_config.capacity * 2; - s_rateLimiter.setRateLimiterConfig(s_config); + SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity = SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity * 2; + + RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](1); + rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); + uint64[] memory chainSelectors = new uint64[](1); + chainSelectors[0] = SRC_CHAIN_1_SELECTOR; - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 2, bucket.tokens); + MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter + .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.rate); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.capacity); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity / 2, bucket.tokens); assertEq(BLOCK_TIME, bucket.lastUpdated); uint256 warpTime = 4; vm.warp(BLOCK_TIME + warpTime); - bucket = s_rateLimiter.currentRateLimiterState(); + bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 2 + warpTime * s_config.rate, bucket.tokens); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.rate); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.capacity); + assertEq( + SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity / 2 + warpTime * SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.tokens + ); assertEq(BLOCK_TIME + warpTime, bucket.lastUpdated); vm.warp(BLOCK_TIME + warpTime * 100); // Bucket overflow - bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.capacity, bucket.tokens); + bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.tokens); } // Reverts @@ -117,131 +219,131 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe vm.warp(BLOCK_TIME - 1); vm.expectRevert(stdError.arithmeticError); - s_rateLimiter.currentRateLimiterState(); - } -} - -/// @notice #setRateLimiterConfig -contract MultiAggregateRateLimiter_setRateLimiterConfig is MultiAggregateRateLimiterSetup { - event ConfigChanged(RateLimiter.Config config); - - function test_Owner_Success() public { - setConfig(); - } - - function test_TokenLimitAdmin_Success() public { - vm.startPrank(ADMIN); - setConfig(); - } - - function setConfig() private { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - - if (bucket.isEnabled) { - s_config = RateLimiter.Config({isEnabled: false, rate: 0, capacity: 0}); - } else { - s_config = RateLimiter.Config({isEnabled: true, rate: 100, capacity: 200}); - } - - vm.expectEmit(); - emit ConfigChanged(s_config); - - s_rateLimiter.setRateLimiterConfig(s_config); - - bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.isEnabled, bucket.isEnabled); - } - - // Reverts - - function test_OnlyOnlyCallableByAdminOrOwner_Revert() public { - vm.startPrank(STRANGER); - - vm.expectRevert(RateLimiter.OnlyCallableByAdminOrOwner.selector); - - s_rateLimiter.setRateLimiterConfig(s_config); + s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); } } -/// @notice #_rateLimitValue -contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterSetup { - event TokensConsumed(uint256 tokens); - - function test_RateLimitValueSuccess_gas() public { - vm.pauseGasMetering(); - // start from blocktime that does not equal rate limiter init timestamp - vm.warp(BLOCK_TIME + 1); - - // 15 (tokens) * 4 (price) * 2 (number of times) > 100 (capacity) - uint256 numberOfTokens = 15; - uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; - - vm.expectEmit(); - emit TokensConsumed(value); - - vm.resumeGasMetering(); - s_rateLimiter.rateLimitValue(value); - vm.pauseGasMetering(); - - // Get the updated bucket status - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - // Assert the proper value has been taken out of the bucket - assertEq(bucket.capacity - value, bucket.tokens); - - // Since value * 2 > bucket.capacity we cannot take it out twice. - // Expect a revert when we try, with a wait time. - uint256 waitTime = 4; - vm.expectRevert( - abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) - ); - s_rateLimiter.rateLimitValue(value); - - // Move the block time forward by 10 so the bucket refills by 10 * rate - vm.warp(BLOCK_TIME + 1 + waitTime); - - // The bucket has filled up enough so we can take out more tokens - s_rateLimiter.rateLimitValue(value); - bucket = s_rateLimiter.currentRateLimiterState(); - assertEq(bucket.capacity - value + waitTime * s_config.rate - value, bucket.tokens); - vm.resumeGasMetering(); - } - - // Reverts - - function test_AggregateValueMaxCapacityExceeded_Revert() public { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - - uint256 numberOfTokens = 100; - uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiter.AggregateValueMaxCapacityExceeded.selector, bucket.capacity, (numberOfTokens * TOKEN_PRICE) / 1e18 - ) - ); - s_rateLimiter.rateLimitValue(value); - } -} - -/// @notice #_getTokenValue -contract MultiAggregateRateLimiter__getTokenValue is MultiAggregateRateLimiterSetup { - function test_GetTokenValue_Success() public view { - uint256 numberOfTokens = 10; - Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); - uint256 value = s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); - assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); - } - - // Reverts - function test_NoTokenPrice_Reverts() public { - address tokenWithNoPrice = makeAddr("Token with no price"); - Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); - - vm.expectRevert(abi.encodeWithSelector(AggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); - s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); - } -} +// /// @notice #setRateLimiterConfig +// contract MultiAggregateRateLimiter_setRateLimiterConfig is MultiAggregateRateLimiterSetup { +// event ConfigChanged(RateLimiter.Config config); + +// function test_Owner_Success() public { +// setConfig(); +// } + +// function test_TokenLimitAdmin_Success() public { +// vm.startPrank(ADMIN); +// setConfig(); +// } + +// function setConfig() private { +// RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); +// assertEq(s_config.rate, bucket.rate); +// assertEq(s_config.capacity, bucket.capacity); + +// if (bucket.isEnabled) { +// s_config = RateLimiter.Config({isEnabled: false, rate: 0, capacity: 0}); +// } else { +// s_config = RateLimiter.Config({isEnabled: true, rate: 100, capacity: 200}); +// } + +// vm.expectEmit(); +// emit ConfigChanged(s_config); + +// s_rateLimiter.setRateLimiterConfig(s_config); + +// bucket = s_rateLimiter.currentRateLimiterState(); +// assertEq(s_config.rate, bucket.rate); +// assertEq(s_config.capacity, bucket.capacity); +// assertEq(s_config.isEnabled, bucket.isEnabled); +// } + +// // Reverts + +// function test_OnlyOnlyCallableByAdminOrOwner_Revert() public { +// vm.startPrank(STRANGER); + +// vm.expectRevert(RateLimiter.OnlyCallableByAdminOrOwner.selector); + +// s_rateLimiter.setRateLimiterConfig(s_config); +// } +// } + +// /// @notice #_rateLimitValue +// contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterSetup { +// event TokensConsumed(uint256 tokens); + +// function test_RateLimitValueSuccess_gas() public { +// vm.pauseGasMetering(); +// // start from blocktime that does not equal rate limiter init timestamp +// vm.warp(BLOCK_TIME + 1); + +// // 15 (tokens) * 4 (price) * 2 (number of times) > 100 (capacity) +// uint256 numberOfTokens = 15; +// uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; + +// vm.expectEmit(); +// emit TokensConsumed(value); + +// vm.resumeGasMetering(); +// s_rateLimiter.rateLimitValue(value); +// vm.pauseGasMetering(); + +// // Get the updated bucket status +// RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); +// // Assert the proper value has been taken out of the bucket +// assertEq(bucket.capacity - value, bucket.tokens); + +// // Since value * 2 > bucket.capacity we cannot take it out twice. +// // Expect a revert when we try, with a wait time. +// uint256 waitTime = 4; +// vm.expectRevert( +// abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) +// ); +// s_rateLimiter.rateLimitValue(value); + +// // Move the block time forward by 10 so the bucket refills by 10 * rate +// vm.warp(BLOCK_TIME + 1 + waitTime); + +// // The bucket has filled up enough so we can take out more tokens +// s_rateLimiter.rateLimitValue(value); +// bucket = s_rateLimiter.currentRateLimiterState(); +// assertEq(bucket.capacity - value + waitTime * s_config.rate - value, bucket.tokens); +// vm.resumeGasMetering(); +// } + +// // Reverts + +// function test_AggregateValueMaxCapacityExceeded_Revert() public { +// RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); + +// uint256 numberOfTokens = 100; +// uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; + +// vm.expectRevert( +// abi.encodeWithSelector( +// RateLimiter.AggregateValueMaxCapacityExceeded.selector, bucket.capacity, (numberOfTokens * TOKEN_PRICE) / 1e18 +// ) +// ); +// s_rateLimiter.rateLimitValue(value); +// } +// } + +// /// @notice #_getTokenValue +// contract MultiAggregateRateLimiter__getTokenValue is MultiAggregateRateLimiterSetup { +// function test_GetTokenValue_Success() public view { +// uint256 numberOfTokens = 10; +// Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); +// uint256 value = s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); +// assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); +// } + +// // Reverts +// function test_NoTokenPrice_Reverts() public { +// address tokenWithNoPrice = makeAddr("Token with no price"); +// Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); + +// vm.expectRevert(abi.encodeWithSelector(MultiAggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); +// s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); +// } +// } From f3f9899d2042dab2533789c097b835d6b82a1957 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 22 May 2024 12:06:28 +0200 Subject: [PATCH 03/23] feat: convert multi-arl contract to message validator --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 158 +++++++++++++++++- .../ccip/interfaces/IMessageValidator.sol | 8 +- .../MultiAggregateRateLimiterHelper.sol | 6 +- .../MultiAggregateRateLimiter.t.sol | 31 +++- 4 files changed, 191 insertions(+), 12 deletions(-) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index eba1130a4d..564f9dd7ab 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IMessageValidator} from "./interfaces/IMessageValidator.sol"; import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; +import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; import {Client} from "./libraries/Client.sol"; import {RateLimiterNoEvents} from "./libraries/RateLimiterNoEvents.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; @@ -11,21 +13,49 @@ import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of /// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). -contract MultiAggregateRateLimiter is OwnerIsCreator { +contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { using RateLimiterNoEvents for RateLimiterNoEvents.TokenBucket; using USDPriceWith18Decimals for uint224; + using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + error UnauthorizedCaller(address caller); error PriceNotFoundForToken(address token); error UpdateLengthMismatch(); + error ZeroAddressNotAllowed(); event RateLimiterConfigUpdated(uint64 indexed chainSelector, RateLimiterNoEvents.Config config); event RateLimiterTokensConsumed(uint64 indexed chainSelector, uint256 tokens); event AdminSet(address newAdmin); + event PriceRegistrySet(address newPriceRegistry); + event TokenAggregateRateLimitAdded(address sourceToken, address destToken); + event TokenAggregateRateLimitRemoved(address sourceToken, address destToken); + event AuthorizedCallerAdded(address caller); + event AuthorizedCallerRemoved(address caller); - // The address of the token limit admin that has the same permissions as the owner. + /// @notice RateLimitToken struct containing both the source and destination token addresses + struct RateLimitToken { + address sourceToken; + address destToken; + } + + /// @notice Update args for changing the authorized callers + struct AuthorizedCallerArgs { + address[] addedCallers; + address[] removedCallers; + } + + /// @dev Tokens that should be included in Aggregate Rate Limiting (from dest -> source) + EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensDestToSource; + + /// @dev Set of callers that can call the validation functions (this is required since the validations modify state) + mapping(address authorizedCaller => bool isAuthorized) internal s_authorizedCallers; + + /// @notice The address of the token limit admin that has the same permissions as the owner. address internal s_admin; + /// @notice The address of the PriceRegistry used to query token values for ratelimiting + address internal s_priceRegistry; - // Rate limiter token bucket states per chain + /// @notice Rate limiter token bucket states per chain mapping(uint64 chainSelector => RateLimiterNoEvents.TokenBucket rateLimiter) s_rateLimitersByChainSelector; /// @notice A collection of rate limiter configuration updates @@ -37,9 +67,42 @@ contract MultiAggregateRateLimiter is OwnerIsCreator { /// @param rateLimiterConfigs The RateLimiterNoEvents.Configs per chain containing the capacity and refill rate /// of the bucket /// @param admin the admin address to set - constructor(RateLimiterConfigUpdates memory rateLimiterConfigs, address admin) { + /// @param priceRegistry the price registry to set + /// @param authorizedCallers the authorized callers to set + constructor( + RateLimiterConfigUpdates memory rateLimiterConfigs, + address admin, + address priceRegistry, + address[] memory authorizedCallers + ) { _applyRateLimiterConfigUpdates(rateLimiterConfigs); _setAdmin(admin); + _setPriceRegistry(priceRegistry); + _applyAuthorizedCallerUpdates( + AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) + ); + } + + /// @inheritdoc IMessageValidator + function validateIncomingMessage(Client.Any2EVMMessage memory message) external { + if (!s_authorizedCallers[msg.sender]) { + revert UnauthorizedCaller(msg.sender); + } + + uint256 value; + Client.EVMTokenAmount[] memory destTokenAmounts = message.destTokenAmounts; + for (uint256 i; i < destTokenAmounts.length; ++i) { + if (s_rateLimitedTokensDestToSource.contains(destTokenAmounts[i].token)) { + value += _getTokenValue(destTokenAmounts[i], IPriceRegistry(s_priceRegistry)); + } + } + + if (value > 0) _rateLimitValue(message.sourceChainSelector, value); + } + + /// @inheritdoc IMessageValidator + function validateOutgoingMessage(Client.EVM2AnyMessage memory message, uint64 destChainSelector) external { + // TODO: to be implemented (assuming the same rate limiter states are shared for incoming and outgoing messages) } /// @notice Consumes value from the rate limiter bucket based on the token value given. @@ -106,10 +169,97 @@ contract MultiAggregateRateLimiter is OwnerIsCreator { } } + /// @notice Get all tokens which are included in Aggregate Rate Limiting. + /// @return sourceTokens The source representation of the tokens that are rate limited. + /// @return destTokens The destination representation of the tokens that are rate limited. + /// @dev the order of IDs in the list is **not guaranteed**, therefore, if ordering matters when + /// making successive calls, one should keep the blockheight constant to ensure a consistent result. + function getAllRateLimitTokens() external view returns (address[] memory sourceTokens, address[] memory destTokens) { + sourceTokens = new address[](s_rateLimitedTokensDestToSource.length()); + destTokens = new address[](s_rateLimitedTokensDestToSource.length()); + + for (uint256 i = 0; i < s_rateLimitedTokensDestToSource.length(); ++i) { + (address destToken, address sourceToken) = s_rateLimitedTokensDestToSource.at(i); + sourceTokens[i] = sourceToken; + destTokens[i] = destToken; + } + return (sourceTokens, destTokens); + } + + /// @notice Adds or removes tokens from being used in Aggregate Rate Limiting. + /// @param removes - A list of one or more tokens to be removed. + /// @param adds - A list of one or more tokens to be added. + function updateRateLimitTokens( + RateLimitToken[] memory removes, + RateLimitToken[] memory adds + ) external onlyAdminOrOwner { + for (uint256 i = 0; i < removes.length; ++i) { + if (s_rateLimitedTokensDestToSource.remove(removes[i].destToken)) { + emit TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); + } + } + + for (uint256 i = 0; i < adds.length; ++i) { + if (s_rateLimitedTokensDestToSource.set(adds[i].destToken, adds[i].sourceToken)) { + emit TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); + } + } + } + + /// @notice Sets the Price Registry address + /// @param newPriceRegistry the address of the new PriceRegistry + /// @dev precondition The address must be a non-zero address + function setPriceRegistry(address newPriceRegistry) external onlyAdminOrOwner { + _setPriceRegistry(newPriceRegistry); + } + + /// @notice Sets the Price Registry address + /// @param newPriceRegistry the address of the new PriceRegistry + /// @dev precondition The address must be a non-zero address + function _setPriceRegistry(address newPriceRegistry) internal { + if (newPriceRegistry == address(0)) { + revert ZeroAddressNotAllowed(); + } + + s_priceRegistry = newPriceRegistry; + emit PriceRegistrySet(newPriceRegistry); + } + // ================================================================ // │ Access │ // ================================================================ + /// @notice Updates the callers that are authorized to call the message validation functions + /// @param authorizedCallerArgs Callers to add and remove + function applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) external onlyAdminOrOwner { + _applyAuthorizedCallerUpdates(authorizedCallerArgs); + } + + /// @notice Updates the callers that are authorized to call the message validation functions + /// @param authorizedCallerArgs Callers to add and remove + function _applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) internal { + address[] memory addedCallers = authorizedCallerArgs.addedCallers; + for (uint256 i; i < addedCallers.length; ++i) { + address caller = addedCallers[i]; + + if (caller == address(0)) { + revert ZeroAddressNotAllowed(); + } + + s_authorizedCallers[caller] = true; + emit AuthorizedCallerAdded(caller); + } + + address[] memory removedCallers = authorizedCallerArgs.removedCallers; + for (uint256 i; i < removedCallers.length; ++i) { + address caller = removedCallers[i]; + + delete s_authorizedCallers[caller]; + // TODO: only emit if value was present + emit AuthorizedCallerRemoved(caller); + } + } + /// @notice Gets the token limit admin address. /// @return the token limit admin address. function getTokenLimitAdmin() external view returns (address) { diff --git a/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol b/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol index c0eff9cc5e..ab3e23b1bb 100644 --- a/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol +++ b/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + import {Client} from "../libraries/Client.sol"; /// @notice Interface for plug-in message validator contracts that intercept OffRamp & OnRamp messages @@ -10,9 +13,10 @@ interface IMessageValidator { /// @notice Validates the given OffRamp message. Reverts on validation failure /// @param message to validate - function validateIncomingMessage(Client.Any2EVMMessage memory message) external view; + function validateIncomingMessage(Client.Any2EVMMessage memory message) external; /// @notice Validates the given OnRamp message. Reverts on validation failure /// @param message to valdidate - function validateOutgoingMessages(Client.EVM2AnyMessage memory message) external view; + /// @param destChainSelector dest chain selector where the message is being sent to + function validateOutgoingMessage(Client.EVM2AnyMessage memory message, uint64 destChainSelector) external; } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index f70b7ba2f0..70f49019ec 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -8,8 +8,10 @@ import {Client} from "../../libraries/Client.sol"; contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { constructor( MultiAggregateRateLimiter.RateLimiterConfigUpdates memory rateLimiterConfigs, - address admin - ) MultiAggregateRateLimiter(rateLimiterConfigs, admin) {} + address admin, + address priceRegistry, + address[] memory authorizedCallers + ) MultiAggregateRateLimiter(rateLimiterConfigs, admin, priceRegistry, authorizedCallers) {} function rateLimitValue(uint64 chainSelector, uint256 value) public { _rateLimitValue(chainSelector, value); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 7f79ce6b1b..80cfa84196 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -26,6 +26,9 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { RateLimiterNoEvents.Config internal SRC_CHAIN_2_RATE_LIMITER_CONFIG = RateLimiterNoEvents.Config({isEnabled: true, rate: 10, capacity: 200}); + address internal immutable MOCK_OFFRAMP = address(1111); + address internal immutable MOCK_ONRAMP = address(1112); + function setUp() public virtual override(BaseTest, PriceRegistrySetup) { BaseTest.setUp(); PriceRegistrySetup.setUp(); @@ -44,7 +47,12 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); - s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); + address[] memory authorizedCallers = new address[](2); + authorizedCallers[0] = MOCK_OFFRAMP; + authorizedCallers[1] = MOCK_ONRAMP; + + s_rateLimiter = + new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); } } @@ -59,8 +67,13 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + address[] memory authorizedCallers = new address[](2); + authorizedCallers[0] = MOCK_OFFRAMP; + authorizedCallers[1] = MOCK_ONRAMP; + vm.recordLogs(); - s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); + s_rateLimiter = + new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); // Single log for AdminSet Vm.Log[] memory logEntries = vm.getRecordedLogs(); @@ -77,11 +90,16 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + address[] memory authorizedCallers = new address[](2); + authorizedCallers[0] = MOCK_OFFRAMP; + authorizedCallers[1] = MOCK_ONRAMP; + vm.expectEmit(); emit RateLimiterConfigUpdated(SRC_CHAIN_1_SELECTOR, SRC_CHAIN_1_RATE_LIMITER_CONFIG); vm.recordLogs(); - s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); + s_rateLimiter = + new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); // Log for AdminSet + RateLimiterConfigSet Vm.Log[] memory logEntries = vm.getRecordedLogs(); @@ -107,13 +125,18 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + address[] memory authorizedCallers = new address[](2); + authorizedCallers[0] = MOCK_OFFRAMP; + authorizedCallers[1] = MOCK_ONRAMP; + vm.expectEmit(); emit RateLimiterConfigUpdated(SRC_CHAIN_1_SELECTOR, SRC_CHAIN_1_RATE_LIMITER_CONFIG); vm.expectEmit(); emit RateLimiterConfigUpdated(SRC_CHAIN_2_SELECTOR, SRC_CHAIN_2_RATE_LIMITER_CONFIG); - s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN); + s_rateLimiter = + new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); assertEq(OWNER, s_rateLimiter.owner()); From 9843abeeb83873a2a231789450efa944868a734c Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 22 May 2024 12:14:28 +0200 Subject: [PATCH 04/23] perf: remove PriceRegistry from MultiOffRamp --- .../src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 10 ++++------ .../ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol | 12 ++++-------- .../test/offRamp/EVM2EVMMultiOffRampSetup.t.sol | 13 ++++++------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 7c3701a7fc..4170132df3 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -10,7 +10,6 @@ import {IAny2EVMOffRamp} from "../interfaces/IAny2EVMOffRamp.sol"; import {IMessageValidator} from "../interfaces/IMessageValidator.sol"; import {IMultiCommitStore} from "../interfaces/IMultiCommitStore.sol"; import {IPool} from "../interfaces/IPool.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; import {IRMN} from "../interfaces/IRMN.sol"; import {IRouter} from "../interfaces/IRouter.sol"; @@ -109,11 +108,10 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN struct DynamicConfig { uint32 permissionLessExecutionThresholdSeconds; // ─╮ Waiting time before manual execution is enabled address router; // ─────────────────────────────────╯ Router address - address priceRegistry; // ──────────╮ Price registry address - uint16 maxNumberOfTokensPerMsg; // │ Maximum number of ERC20 token transfers that can be included per message - uint32 maxDataBytes; // │ Maximum payload data size in bytes - uint32 maxPoolReleaseOrMintGas; // ─╯ Maximum amount of gas passed on to token pool when calling releaseOrMint - address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) + uint16 maxNumberOfTokensPerMsg; // ──╮ Maximum number of ERC20 token transfers that can be included per message + uint32 maxDataBytes; // │ Maximum payload data size in bytes + uint32 maxPoolReleaseOrMintGas; // │ Maximum amount of gas passed on to token pool when calling releaseOrMint + address messageValidator; // ────────╯ Optional message validator to validate incoming messages (zero address = no validator) } /// @notice Struct that represents a message route (sender -> receiver and source chain) diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index 00fc3b0351..661c68a794 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -41,8 +41,7 @@ contract EVM2EVMMultiOffRamp_constructor is EVM2EVMMultiOffRampSetup { chainSelector: DEST_CHAIN_SELECTOR, rmnProxy: address(s_mockRMN) }); - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - generateDynamicMultiOffRampConfig(address(s_destRouter), address(s_priceRegistry)); + EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = generateDynamicMultiOffRampConfig(address(s_destRouter)); EVM2EVMMultiOffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new EVM2EVMMultiOffRamp.SourceChainConfigArgs[](2); @@ -155,8 +154,7 @@ contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { function test_SetDynamicConfig_Success() public { EVM2EVMMultiOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)); + EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = generateDynamicMultiOffRampConfig(USER_3); bytes memory onchainConfig = abi.encode(dynamicConfig); vm.expectEmit(); @@ -186,8 +184,7 @@ contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { function test_NonOwner_Revert() public { vm.startPrank(STRANGER); - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - generateDynamicMultiOffRampConfig(USER_3, address(s_priceRegistry)); + EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = generateDynamicMultiOffRampConfig(USER_3); vm.expectRevert("Only callable by owner"); @@ -197,8 +194,7 @@ contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { } function test_RouterZeroAddress_Revert() public { - EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = - generateDynamicMultiOffRampConfig(ZERO_ADDRESS, ZERO_ADDRESS); + EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = generateDynamicMultiOffRampConfig(ZERO_ADDRESS); vm.expectRevert(EVM2EVMMultiOffRamp.ZeroAddressNotAllowed.selector); diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol index d6f9120b50..344f82f34a 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol @@ -83,7 +83,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet s_valid_signers, s_valid_transmitters, s_f, - abi.encode(generateDynamicMultiOffRampConfig(address(router), address(s_priceRegistry))), + abi.encode(generateDynamicMultiOffRampConfig(address(router))), s_offchainConfigVersion, abi.encode("") ); @@ -204,14 +204,14 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet }); } - function generateDynamicMultiOffRampConfig( - address router, - address priceRegistry - ) internal pure returns (EVM2EVMMultiOffRamp.DynamicConfig memory) { + function generateDynamicMultiOffRampConfig(address router) + internal + pure + returns (EVM2EVMMultiOffRamp.DynamicConfig memory) + { return EVM2EVMMultiOffRamp.DynamicConfig({ permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, router: router, - priceRegistry: priceRegistry, maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, maxDataBytes: MAX_DATA_SIZE, maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, @@ -393,7 +393,6 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet ) public pure { assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); assertEq(a.router, b.router); - assertEq(a.priceRegistry, b.priceRegistry); assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); assertEq(a.maxDataBytes, b.maxDataBytes); assertEq(a.maxPoolReleaseOrMintGas, b.maxPoolReleaseOrMintGas); From f53a3bcbda35b07ada9df5f3888272d92b55609a Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 22 May 2024 12:16:14 +0200 Subject: [PATCH 05/23] refactor: move multi-ARL to validators --- .../helpers/MultiAggregateRateLimiterHelper.sol | 2 +- .../rateLimiter/MultiAggregateRateLimiter.t.sol | 2 +- .../MultiAggregateRateLimiter.sol | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) rename contracts/src/v0.8/ccip/{ => validators}/MultiAggregateRateLimiter.sol (96%) diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index 70f49019ec..2cc46bc2ee 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; import {Client} from "../../libraries/Client.sol"; +import {MultiAggregateRateLimiter} from "../../validators/MultiAggregateRateLimiter.sol"; contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { constructor( diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 80cfa84196..c17df2dfe6 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -3,10 +3,10 @@ pragma solidity 0.8.24; import {Vm} from "forge-std/Vm.sol"; -import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; +import {MultiAggregateRateLimiter} from "../../validators/MultiAggregateRateLimiter.sol"; import {BaseTest} from "../BaseTest.t.sol"; import {MultiAggregateRateLimiterHelper} from "../helpers/MultiAggregateRateLimiterHelper.sol"; import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol similarity index 96% rename from contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol rename to contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol index 564f9dd7ab..26cf897970 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IMessageValidator} from "./interfaces/IMessageValidator.sol"; -import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; - -import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; -import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; -import {Client} from "./libraries/Client.sol"; -import {RateLimiterNoEvents} from "./libraries/RateLimiterNoEvents.sol"; -import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; +import {IMessageValidator} from "../interfaces/IMessageValidator.sol"; +import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {EnumerableMapAddresses} from "../../shared/enumerable/EnumerableMapAddresses.sol"; +import {Client} from "../libraries/Client.sol"; +import {RateLimiterNoEvents} from "../libraries/RateLimiterNoEvents.sol"; +import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.sol"; /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of From 18b71256cd71c94bd572d859a996dc9c593152d5 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 22 May 2024 12:20:44 +0200 Subject: [PATCH 06/23] perf: remove PriceRegistry param from getTokenValue --- .../test/helpers/MultiAggregateRateLimiterHelper.sol | 7 ++----- .../ccip/validators/MultiAggregateRateLimiter.sol | 11 +++++------ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index 2cc46bc2ee..668611c210 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -17,10 +17,7 @@ contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { _rateLimitValue(chainSelector, value); } - function getTokenValue( - Client.EVMTokenAmount memory tokenAmount, - IPriceRegistry priceRegistry - ) public view returns (uint256) { - return _getTokenValue(tokenAmount, priceRegistry); + function getTokenValue(Client.EVMTokenAmount memory tokenAmount) public view returns (uint256) { + return _getTokenValue(tokenAmount); } } diff --git a/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol index 26cf897970..5a33b437c7 100644 --- a/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol @@ -93,7 +93,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { Client.EVMTokenAmount[] memory destTokenAmounts = message.destTokenAmounts; for (uint256 i; i < destTokenAmounts.length; ++i) { if (s_rateLimitedTokensDestToSource.contains(destTokenAmounts[i].token)) { - value += _getTokenValue(destTokenAmounts[i], IPriceRegistry(s_priceRegistry)); + value += _getTokenValue(destTokenAmounts[i]); } } @@ -113,13 +113,12 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { emit RateLimiterTokensConsumed(chainSelector, value); } - function _getTokenValue( - Client.EVMTokenAmount memory tokenAmount, - IPriceRegistry priceRegistry - ) internal view returns (uint256) { + /// @notice Retrieves the token value for a token using the PriceRegistry + /// @return tokenValue USD value in 18 decimals + function _getTokenValue(Client.EVMTokenAmount memory tokenAmount) internal view returns (uint256) { // not fetching validated price, as price staleness is not important for value-based rate limiting // we only need to verify the price is not 0 - uint224 pricePerToken = priceRegistry.getTokenPrice(tokenAmount.token).value; + uint224 pricePerToken = IPriceRegistry(s_priceRegistry).getTokenPrice(tokenAmount.token).value; if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmount.token); return pricePerToken._calcUSDValueFromTokenAmount(tokenAmount.amount); } From ea6d0cd7728704f77224b2a23c328c38dbe6644f Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 22 May 2024 12:34:02 +0200 Subject: [PATCH 07/23] feat: catch all validation failures and create IMessageValidator helper --- .../ccip/interfaces/IMessageValidator.sol | 4 +-- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 7 ++++-- .../test/helpers/MessageValidatorHelper.sol | 25 +++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol diff --git a/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol b/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol index ab3e23b1bb..ff30c27f3c 100644 --- a/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol +++ b/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol @@ -7,9 +7,9 @@ import {Client} from "../libraries/Client.sol"; /// and perform validations on top of the messages. All validation functions are expected to /// revert on validation failures. interface IMessageValidator { - /// @notice The error that is expected to be thrown on validation failures + /// @notice Common error that can be thrown on validation failures and used by consumers /// @param errorReason abi encoded revert reason - error MessageValidationFailure(bytes errorReason); + error MessageValidationError(bytes errorReason); /// @notice Validates the given OffRamp message. Reverts on validation failure /// @param message to validate diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 4170132df3..8ad93d805e 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -500,7 +500,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN ReceiverError.selector == bytes4(err) || TokenHandlingError.selector == bytes4(err) || Internal.InvalidEVMAddress.selector == bytes4(err) || InvalidDataLength.selector == bytes4(err) || CallWithExactGas.NoContract.selector == bytes4(err) || NotACompatiblePool.selector == bytes4(err) - || IMessageValidator.MessageValidationFailure.selector == bytes4(err) + || IMessageValidator.MessageValidationError.selector == bytes4(err) ) { // If CCIP receiver execution is not successful, bubble up receiver revert data, // prepended by the 4 bytes of ReceiverError.selector, TokenHandlingError.selector or InvalidPoolAddress.selector. @@ -555,7 +555,10 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN address messageValidator = s_dynamicConfig.messageValidator; if (messageValidator != address(0)) { - IMessageValidator(messageValidator).validateIncomingMessage(any2EvmMessage); + try IMessageValidator(messageValidator).validateIncomingMessage(any2EvmMessage) {} + catch (bytes memory err) { + revert IMessageValidator.MessageValidationError(err); + } } (bool success, bytes memory returnData,) = IRouter(s_dynamicConfig.router).routeMessage( diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol new file mode 100644 index 0000000000..693ddc31aa --- /dev/null +++ b/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import "../../interfaces/IMessageValidator.sol"; + +contract MessageValidatorHelper is IMessageValidator { + error IncomingMessageValidationError(bytes errorReason); + + mapping(bytes32 messageId => bool isInvalid) internal s_invalidMessageIds; + + constructor() {} + + /// @inheritdoc IMessageValidator + function validateIncomingMessage(Client.Any2EVMMessage memory message) external view { + if (s_invalidMessageIds[message.messageId]) { + revert IncomingMessageValidationError(bytes("Invalid message")); + } + } + + /// @inheritdoc IMessageValidator + function validateOutgoingMessage(Client.EVM2AnyMessage memory, uint64) external pure { + // TODO: to be implemented + return; + } +} From 6e1513651870716b22847c86e39860b0e691aa9c Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 22 May 2024 14:14:37 +0200 Subject: [PATCH 08/23] test: message validation in offramp --- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 11 +- .../test/helpers/MessageValidatorHelper.sol | 4 + .../test/offRamp/EVM2EVMMultiOffRamp.t.sol | 176 ++++++++++++------ .../offRamp/EVM2EVMMultiOffRampSetup.t.sol | 14 ++ tools/ci/ccip_lcov_prune | 4 +- 5 files changed, 147 insertions(+), 62 deletions(-) diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 8ad93d805e..5277807c92 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -22,6 +22,8 @@ import {OCR2BaseNoChecks} from "../ocr/OCR2BaseNoChecks.sol"; import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; +import {console} from "forge-std/console.sol"; + /// @notice EVM2EVMOffRamp enables OCR networks to execute multiple messages /// in an OffRamp in a single transaction. /// @dev The EVM2EVMOnRamp, CommitStore and EVM2EVMOffRamp form an xchain upgradeable unit. Any change to one of them @@ -496,11 +498,12 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN ) internal returns (Internal.MessageExecutionState, bytes memory) { try this.executeSingleMessage(message, offchainTokenData) {} catch (bytes memory err) { + bytes4 errorSelector = bytes4(err); if ( - ReceiverError.selector == bytes4(err) || TokenHandlingError.selector == bytes4(err) - || Internal.InvalidEVMAddress.selector == bytes4(err) || InvalidDataLength.selector == bytes4(err) - || CallWithExactGas.NoContract.selector == bytes4(err) || NotACompatiblePool.selector == bytes4(err) - || IMessageValidator.MessageValidationError.selector == bytes4(err) + ReceiverError.selector == errorSelector || TokenHandlingError.selector == errorSelector + || Internal.InvalidEVMAddress.selector == errorSelector || InvalidDataLength.selector == errorSelector + || CallWithExactGas.NoContract.selector == errorSelector || NotACompatiblePool.selector == errorSelector + || IMessageValidator.MessageValidationError.selector == errorSelector ) { // If CCIP receiver execution is not successful, bubble up receiver revert data, // prepended by the 4 bytes of ReceiverError.selector, TokenHandlingError.selector or InvalidPoolAddress.selector. diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol index 693ddc31aa..15a0bec7cc 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol @@ -10,6 +10,10 @@ contract MessageValidatorHelper is IMessageValidator { constructor() {} + function setMessageIdValidationState(bytes32 messageId, bool isInvalid) external { + s_invalidMessageIds[messageId] = isInvalid; + } + /// @inheritdoc IMessageValidator function validateIncomingMessage(Client.Any2EVMMessage memory message) external view { if (s_invalidMessageIds[message.messageId]) { diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index 661c68a794..5d585c0046 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -8,6 +8,7 @@ import {IPool} from "../../interfaces/IPool.sol"; import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; import {RMN} from "../../RMN.sol"; import {Router} from "../../Router.sol"; +import {IMessageValidator} from "../../interfaces/IMessageValidator.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {Pool} from "../../libraries/Pool.sol"; @@ -18,6 +19,7 @@ import {TokenPool} from "../../pools/TokenPool.sol"; import {EVM2EVMMultiOffRampHelper} from "../helpers/EVM2EVMMultiOffRampHelper.sol"; import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; +import {MessageValidatorHelper} from "../helpers/MessageValidatorHelper.sol"; import {ConformingReceiver} from "../helpers/receivers/ConformingReceiver.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {MaybeRevertMessageReceiverNo165} from "../helpers/receivers/MaybeRevertMessageReceiverNo165.sol"; @@ -182,6 +184,23 @@ contract EVM2EVMMultiOffRamp_setDynamicConfig is EVM2EVMMultiOffRampSetup { _assertSameConfig(dynamicConfig, newConfig); } + function test_SetDynamicConfigWithValidator_Success() public { + EVM2EVMMultiOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); + EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = generateDynamicMultiOffRampConfig(USER_3); + dynamicConfig.messageValidator = address(s_messageValidator); + bytes memory onchainConfig = abi.encode(dynamicConfig); + + vm.expectEmit(); + emit ConfigSet(staticConfig, dynamicConfig); + + s_offRamp.setOCR2Config( + s_valid_signers, s_valid_transmitters, s_f, onchainConfig, s_offchainConfigVersion, abi.encode("") + ); + + EVM2EVMMultiOffRamp.DynamicConfig memory newConfig = s_offRamp.getDynamicConfig(); + _assertSameConfig(dynamicConfig, newConfig); + } + function test_NonOwner_Revert() public { vm.startPrank(STRANGER); EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = generateDynamicMultiOffRampConfig(USER_3); @@ -1104,24 +1123,39 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); } - // function test_executeSingleMessage_WithTokens_Success() public { - // Internal.EVM2EVMMessage memory message = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; - // bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); - // vm.expectCall( - // s_destPoolByToken[s_destTokens[0]], - // abi.encodeWithSelector( - // LockReleaseTokenPool.releaseOrMint.selector, - // abi.encode(message.sender), - // message.receiver, - // message.tokenAmounts[0].amount, - // SOURCE_CHAIN_SELECTOR_1, - // abi.decode(message.sourceTokenData[0], (Internal.SourceTokenData)), - // offchainTokenData[0] - // ) - // ); + function test_executeSingleMessage_WithTokens_Success() public { + Internal.EVM2EVMMessage memory message = _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)[0]; + bytes[] memory offchainTokenData = new bytes[](message.tokenAmounts.length); + Internal.SourceTokenData memory sourceTokenData = abi.decode(message.sourceTokenData[0], (Internal.SourceTokenData)); - // s_offRamp.executeSingleMessage(message, offchainTokenData); - // } + vm.expectCall( + s_destPoolByToken[s_destTokens[0]], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(message.sender), + receiver: message.receiver, + amount: message.tokenAmounts[0].amount, + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: "" + }) + ) + ); + + s_offRamp.executeSingleMessage(message, offchainTokenData); + } + + function test_executeSingleMessage_WithValidation_Success() public { + vm.stopPrank(); + vm.startPrank(OWNER); + _enableMessageValidator(); + vm.startPrank(address(s_offRamp)); + Internal.EVM2EVMMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + } function test_NonContract_Success() public { Internal.EVM2EVMMessage memory message = @@ -1179,6 +1213,23 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { vm.expectRevert(EVM2EVMMultiOffRamp.CanOnlySelfCall.selector); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); } + + function test_executeSingleMessage_WithFailingValidation_Revert() public { + vm.stopPrank(); + vm.startPrank(OWNER); + _enableMessageValidator(); + vm.startPrank(address(s_offRamp)); + Internal.EVM2EVMMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + s_messageValidator.setMessageIdValidationState(message.messageId, true); + vm.expectRevert( + abi.encodeWithSelector( + IMessageValidator.MessageValidationError.selector, + abi.encodeWithSelector(MessageValidatorHelper.IncomingMessageValidationError.selector, bytes("Invalid message")) + ) + ); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + } } contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { @@ -1876,6 +1927,59 @@ contract EVM2EVMMultiOffRamp_report is EVM2EVMMultiOffRampSetup { s_offRamp.report(abi.encode(reports)); } + function test_MultipleReportsWithPartialValidationFailures_Success() public { + _enableMessageValidator(); + + Internal.EVM2EVMMessage[] memory messages1 = new Internal.EVM2EVMMessage[](2); + Internal.EVM2EVMMessage[] memory messages2 = new Internal.EVM2EVMMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 3); + + Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); + + s_messageValidator.setMessageIdValidationState(messages1[0].messageId, true); + s_messageValidator.setMessageIdValidationState(messages2[0].messageId, true); + + vm.expectEmit(); + emit ExecutionStateChanged( + messages1[0].sourceChainSelector, + messages1[0].sequenceNumber, + messages1[0].messageId, + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + IMessageValidator.MessageValidationError.selector, + abi.encodeWithSelector(MessageValidatorHelper.IncomingMessageValidationError.selector, bytes("Invalid message")) + ) + ); + + vm.expectEmit(); + emit ExecutionStateChanged( + messages1[1].sourceChainSelector, + messages1[1].sequenceNumber, + messages1[1].messageId, + Internal.MessageExecutionState.SUCCESS, + "" + ); + + vm.expectEmit(); + emit ExecutionStateChanged( + messages2[0].sourceChainSelector, + messages2[0].sequenceNumber, + messages2[0].messageId, + Internal.MessageExecutionState.FAILURE, + abi.encodeWithSelector( + IMessageValidator.MessageValidationError.selector, + abi.encodeWithSelector(MessageValidatorHelper.IncomingMessageValidationError.selector, bytes("Invalid message")) + ) + ); + + s_offRamp.report(abi.encode(reports)); + } + // Reverts function test_ZeroReports_Revert() public { @@ -2262,44 +2366,6 @@ contract EVM2EVMMultiOffRamp_releaseOrMintTokens is EVM2EVMMultiOffRampSetup { assertEq(destTokenAmounts[0].token, destToken); } - // TODO: re-add after ARL changes - // function test_OverValueWithARLOff_Success() public { - // // Set a high price to trip the ARL - // uint224 tokenPrice = 3 ** 128; - // Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(s_destFeeToken, tokenPrice); - // s_priceRegistry.updatePrices(priceUpdates); - - // Client.EVMTokenAmount[] memory srcTokenAmounts = getCastedSourceEVMTokenAmountsWithZeroAmounts(); - // uint256 amount1 = 100; - // srcTokenAmounts[0].amount = amount1; - - // bytes memory originalSender = abi.encode(OWNER); - - // bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - // offchainTokenData[0] = abi.encode(0x12345678); - - // bytes[] memory sourceTokenData = _getDefaultSourceTokenData(srcTokenAmounts); - - // vm.expectRevert( - // abi.encodeWithSelector( - // RateLimiter.AggregateValueMaxCapacityExceeded.selector, - // getInboundRateLimiterConfig().capacity, - // (amount1 * tokenPrice) / 1e18 - // ) - // ); - - // // // Expect to fail from ARL - // s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, sourceTokenData, offchainTokenData); - - // // Configure ARL off for token - // EVM2EVMMultiOffRamp.RateLimitToken[] memory removes = new EVM2EVMMultiOffRamp.RateLimitToken[](1); - // removes[0] = EVM2EVMMultiOffRamp.RateLimitToken({sourceToken: s_sourceFeeToken, destToken: s_destFeeToken}); - // s_offRamp.updateRateLimitTokens(removes, new EVM2EVMMultiOffRamp.RateLimitToken[](0)); - - // // Expect the call now succeeds - // s_offRamp.releaseOrMintTokens(srcTokenAmounts, originalSender, OWNER, sourceTokenData, offchainTokenData); - // } - // Revert function test_TokenHandlingError_Reverts() public { diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol index 344f82f34a..bef9bbeddb 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol @@ -17,6 +17,8 @@ import {TokenSetup} from "../TokenSetup.t.sol"; import {EVM2EVMMultiOffRampHelper} from "../helpers/EVM2EVMMultiOffRampHelper.sol"; import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; + +import {MessageValidatorHelper} from "../helpers/MessageValidatorHelper.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {MockCommitStore} from "../mocks/MockCommitStore.sol"; import {MockMultiCommitStore} from "../mocks/MockMultiCommitStore.sol"; @@ -42,6 +44,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet MaybeRevertingBurnMintTokenPool internal s_maybeRevertingPool; EVM2EVMMultiOffRampHelper internal s_offRamp; + MessageValidatorHelper internal s_messageValidator; address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); event ExecutionStateChanged( @@ -57,6 +60,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet PriceRegistrySetup.setUp(); OCR2BaseSetup.setUp(); + s_messageValidator = new MessageValidatorHelper(); s_mockCommitStore = new MockMultiCommitStore(); s_receiver = new MaybeRevertMessageReceiver(false); s_secondary_receiver = new MaybeRevertMessageReceiver(false); @@ -396,6 +400,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); assertEq(a.maxDataBytes, b.maxDataBytes); assertEq(a.maxPoolReleaseOrMintGas, b.maxPoolReleaseOrMintGas); + assertEq(a.messageValidator, b.messageValidator); } function _assertSourceChainConfigEquality( @@ -425,4 +430,13 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet } return sourceTokenData; } + + function _enableMessageValidator() internal { + EVM2EVMMultiOffRamp.DynamicConfig memory dynamicConfig = s_offRamp.getDynamicConfig(); + dynamicConfig.messageValidator = address(s_messageValidator); + bytes memory onchainConfig = abi.encode(dynamicConfig); + s_offRamp.setOCR2Config( + s_valid_signers, s_valid_transmitters, s_f, onchainConfig, s_offchainConfigVersion, abi.encode("") + ); + } } diff --git a/tools/ci/ccip_lcov_prune b/tools/ci/ccip_lcov_prune index 2458d58518..f3c494fc0c 100755 --- a/tools/ci/ccip_lcov_prune +++ b/tools/ci/ccip_lcov_prune @@ -27,8 +27,6 @@ lcov --remove $1 -o $2 \ 'src/v0.8/tests/MockV3Aggregator.sol' \ 'src/v0.8/ccip/applications/CCIPClientExample.sol' \ 'src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol' \ - 'src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol' \ 'src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol' \ - 'src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol' \ - 'src/v0.8/ccip/MultiAggregateRateLimiter.sol' \ + 'src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol' \ --rc lcov_branch_coverage=1 From 54d86d133a15f1cc2266507bd62955e2701821b7 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 22 May 2024 16:06:47 +0200 Subject: [PATCH 09/23] test: multi-arl tests --- .../MultiAggregateRateLimiterHelper.sol | 2 +- .../MultiAggregateRateLimiter.t.sol | 1101 +++++++++++++---- .../validators/MultiAggregateRateLimiter.sol | 60 +- tools/ci/ccip_lcov_prune | 1 - 4 files changed, 930 insertions(+), 234 deletions(-) diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index 668611c210..b055129ae8 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -7,7 +7,7 @@ import {MultiAggregateRateLimiter} from "../../validators/MultiAggregateRateLimi contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { constructor( - MultiAggregateRateLimiter.RateLimiterConfigUpdates memory rateLimiterConfigs, + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory rateLimiterConfigs, address admin, address priceRegistry, address[] memory authorizedCallers diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index c17df2dfe6..0919330c06 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -19,11 +19,12 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { address internal immutable TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; uint224 internal constant TOKEN_PRICE = 4e18; - uint64 internal constant SRC_CHAIN_1_SELECTOR = 5009297550715157269; - RateLimiterNoEvents.Config internal SRC_CHAIN_1_RATE_LIMITER_CONFIG = + uint64 internal constant CHAIN_SELECTOR_1 = 5009297550715157269; + uint64 internal constant CHAIN_SELECTOR_2 = 4949039107694359620; + + RateLimiterNoEvents.Config internal RATE_LIMITER_CONFIG_1 = RateLimiterNoEvents.Config({isEnabled: true, rate: 5, capacity: 100}); - uint64 internal constant SRC_CHAIN_2_SELECTOR = 4949039107694359620; - RateLimiterNoEvents.Config internal SRC_CHAIN_2_RATE_LIMITER_CONFIG = + RateLimiterNoEvents.Config internal RATE_LIMITER_CONFIG_2 = RateLimiterNoEvents.Config({isEnabled: true, rate: 10, capacity: 200}); address internal immutable MOCK_OFFRAMP = address(1111); @@ -36,16 +37,16 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); s_priceRegistry.updatePrices(priceUpdates); - RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](2); - rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; - rateLimiterConfigs[1] = SRC_CHAIN_2_RATE_LIMITER_CONFIG; - - uint64[] memory chainSelectors = new uint64[](2); - chainSelectors[0] = SRC_CHAIN_1_SELECTOR; - chainSelectors[1] = SRC_CHAIN_2_SELECTOR; - - MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter - .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_2, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); address[] memory authorizedCallers = new address[](2); authorizedCallers[0] = MOCK_OFFRAMP; @@ -54,105 +55,112 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); } + + function _assertConfigWithTokenBucketEquality( + RateLimiterNoEvents.Config memory config, + RateLimiterNoEvents.TokenBucket memory tokenBucket + ) internal pure { + assertEq(config.rate, tokenBucket.rate); + assertEq(config.capacity, tokenBucket.capacity); + assertEq(config.capacity, tokenBucket.tokens); + assertEq(config.isEnabled, tokenBucket.isEnabled); + } + + function _assertTokenBucketEquality( + RateLimiterNoEvents.TokenBucket memory tokenBucketA, + RateLimiterNoEvents.TokenBucket memory tokenBucketB + ) internal pure { + assertEq(tokenBucketA.rate, tokenBucketB.rate); + assertEq(tokenBucketA.capacity, tokenBucketB.capacity); + assertEq(tokenBucketA.tokens, tokenBucketB.tokens); + assertEq(tokenBucketA.isEnabled, tokenBucketB.isEnabled); + } } /// @notice #constructor contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup { - event RateLimiterConfigUpdated(uint64 indexed chainSelector, RateLimiterNoEvents.Config config); - - function test_ConstructorNoConfigs_Success() public { - RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](0); - uint64[] memory chainSelectors = new uint64[](0); - - MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter - .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); - - address[] memory authorizedCallers = new address[](2); - authorizedCallers[0] = MOCK_OFFRAMP; - authorizedCallers[1] = MOCK_ONRAMP; + function test_ConstructorNoAuthorizedCallers_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](0); + address[] memory authorizedCallers = new address[](0); vm.recordLogs(); s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); - // Single log for AdminSet + // AdminSet + PriceRegistrySet Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 1); - } - - function test_ConstructorSingleConfig_Success() public { - RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](1); - rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; - - uint64[] memory chainSelectors = new uint64[](1); - chainSelectors[0] = SRC_CHAIN_1_SELECTOR; + assertEq(logEntries.length, 2); - MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter - .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); + assertEq(OWNER, s_rateLimiter.owner()); + assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); + } + function test_ConstructorNoConfigs_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](0); address[] memory authorizedCallers = new address[](2); authorizedCallers[0] = MOCK_OFFRAMP; authorizedCallers[1] = MOCK_ONRAMP; - vm.expectEmit(); - emit RateLimiterConfigUpdated(SRC_CHAIN_1_SELECTOR, SRC_CHAIN_1_RATE_LIMITER_CONFIG); - vm.recordLogs(); s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); - // Log for AdminSet + RateLimiterConfigSet + // AdminSet + PriceRegistrySet + 2 authorized caller sets Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 2); + assertEq(logEntries.length, 4); - RateLimiterNoEvents.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucketSrcChain1.rate); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.capacity); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.tokens); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.isEnabled, bucketSrcChain1.isEnabled); - assertEq(BLOCK_TIME, bucketSrcChain1.lastUpdated); + assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); + assertEq(OWNER, s_rateLimiter.owner()); + assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); } - function test_ConstructorMultipleConfigs_Success() public { - RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](2); - rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; - rateLimiterConfigs[1] = SRC_CHAIN_2_RATE_LIMITER_CONFIG; - - uint64[] memory chainSelectors = new uint64[](2); - chainSelectors[0] = SRC_CHAIN_1_SELECTOR; - chainSelectors[1] = SRC_CHAIN_2_SELECTOR; - - MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter - .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + function test_Constructor_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_2, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); address[] memory authorizedCallers = new address[](2); authorizedCallers[0] = MOCK_OFFRAMP; authorizedCallers[1] = MOCK_ONRAMP; vm.expectEmit(); - emit RateLimiterConfigUpdated(SRC_CHAIN_1_SELECTOR, SRC_CHAIN_1_RATE_LIMITER_CONFIG); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated(CHAIN_SELECTOR_1, RATE_LIMITER_CONFIG_1); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated(CHAIN_SELECTOR_2, RATE_LIMITER_CONFIG_2); vm.expectEmit(); - emit RateLimiterConfigUpdated(SRC_CHAIN_2_SELECTOR, SRC_CHAIN_2_RATE_LIMITER_CONFIG); + emit MultiAggregateRateLimiter.PriceRegistrySet(address(s_priceRegistry)); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerAdded(MOCK_OFFRAMP); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerAdded(MOCK_ONRAMP); s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); assertEq(OWNER, s_rateLimiter.owner()); + assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); - RateLimiterNoEvents.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucketSrcChain1.rate); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.capacity); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucketSrcChain1.tokens); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.isEnabled, bucketSrcChain1.isEnabled); + RateLimiterNoEvents.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketSrcChain1); assertEq(BLOCK_TIME, bucketSrcChain1.lastUpdated); - RateLimiterNoEvents.TokenBucket memory bucketSrcChain2 = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_2_SELECTOR); - assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.rate, bucketSrcChain2.rate); - assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.capacity, bucketSrcChain2.capacity); - assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.capacity, bucketSrcChain2.tokens); - assertEq(SRC_CHAIN_2_RATE_LIMITER_CONFIG.isEnabled, bucketSrcChain2.isEnabled); + RateLimiterNoEvents.TokenBucket memory bucketSrcChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_2, bucketSrcChain2); assertEq(BLOCK_TIME, bucketSrcChain2.lastUpdated); } } @@ -166,11 +174,19 @@ contract MultiAggregateRateLimiter_getTokenLimitAdmin is MultiAggregateRateLimit /// @notice #setAdmin contract MultiAggregateRateLimiter_setAdmin is MultiAggregateRateLimiterSetup { - event AdminSet(address newAdmin); - function test_Owner_Success() public { vm.expectEmit(); - emit AdminSet(STRANGER); + emit MultiAggregateRateLimiter.AdminSet(STRANGER); + + s_rateLimiter.setAdmin(STRANGER); + assertEq(STRANGER, s_rateLimiter.getTokenLimitAdmin()); + } + + function test_Admin_Success() public { + vm.startPrank(ADMIN); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.AdminSet(STRANGER); s_rateLimiter.setAdmin(STRANGER); assertEq(STRANGER, s_rateLimiter.getTokenLimitAdmin()); @@ -186,54 +202,242 @@ contract MultiAggregateRateLimiter_setAdmin is MultiAggregateRateLimiterSetup { } } +/// @notice #setPriceRegistry +contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiterSetup { + function test_Owner_Success() public { + address newAddress = address(42); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.PriceRegistrySet(newAddress); + + s_rateLimiter.setPriceRegistry(newAddress); + assertEq(newAddress, s_rateLimiter.getPriceRegistry()); + } + + function test_Admin_Success() public { + vm.startPrank(ADMIN); + + address newAddress = address(42); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.PriceRegistrySet(newAddress); + + s_rateLimiter.setPriceRegistry(newAddress); + assertEq(newAddress, s_rateLimiter.getPriceRegistry()); + } + + // Reverts + + function test_OnlyOwnerOrAdmin_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + + s_rateLimiter.setPriceRegistry(STRANGER); + } + + function test_ZeroAddress_Revert() public { + vm.expectRevert(MultiAggregateRateLimiter.ZeroAddressNotAllowed.selector); + s_rateLimiter.setPriceRegistry(address(0)); + } +} + +/// @notice #setPriceRegistry +contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLimiterSetup { + function test_OnlyAdd_Success() public { + address[] memory addedCallers = new address[](2); + addedCallers[0] = address(42); + addedCallers[1] = address(43); + + address[] memory removedCallers = new address[](0); + + assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[0]); + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[1]); + + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); + } + + function test_OnlyRemove_Success() public { + address[] memory addedCallers = new address[](0); + + address[] memory removedCallers = new address[](1); + removedCallers[0] = MOCK_OFFRAMP; + + assertTrue(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerRemoved(removedCallers[0]); + + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + } + + function test_AddAndRemove_Success() public { + address[] memory addedCallers = new address[](2); + addedCallers[0] = address(42); + addedCallers[1] = address(43); + + address[] memory removedCallers = new address[](1); + removedCallers[0] = MOCK_OFFRAMP; + + assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); + assertTrue(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[0]); + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[1]); + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerRemoved(removedCallers[0]); + + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); + assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + } + + function test_AddThenRemove_Success() public { + address[] memory addedCallers = new address[](1); + addedCallers[0] = address(42); + + address[] memory removedCallers = new address[](1); + removedCallers[0] = address(42); + + assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[0]); + vm.expectEmit(); + emit MultiAggregateRateLimiter.AuthorizedCallerRemoved(addedCallers[0]); + + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + } + + function test_SkipRemove_Success() public { + address[] memory addedCallers = new address[](0); + + address[] memory removedCallers = new address[](1); + removedCallers[0] = address(42); + + vm.recordLogs(); + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } + + function test_ChangedByAdmin_Success() public { + vm.startPrank(ADMIN); + + address[] memory addedCallers = new address[](0); + + address[] memory removedCallers = new address[](1); + removedCallers[0] = MOCK_OFFRAMP; + + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + + assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + } + + // Reverts + + function test_OnlyOwnerOrAdmin_Revert() public { + vm.startPrank(STRANGER); + vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + + address[] memory addedCallers = new address[](2); + addedCallers[0] = address(42); + addedCallers[1] = address(43); + + address[] memory removedCallers = new address[](0); + + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + } + + function test_ZeroAddressAdd_Revert() public { + address[] memory addedCallers = new address[](1); + addedCallers[0] = address(0); + address[] memory removedCallers = new address[](0); + + vm.expectRevert(MultiAggregateRateLimiter.ZeroAddressNotAllowed.selector); + s_rateLimiter.applyAuthorizedCallerUpdates( + MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) + ); + } +} + /// @notice #getTokenBucket contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { function test_GetTokenBucket_Success() public view { - RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.rate); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.capacity); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.tokens); + RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.tokens); assertEq(BLOCK_TIME, bucket.lastUpdated); } function test_Refill_Success() public { - SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity = SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity * 2; - - RateLimiterNoEvents.Config[] memory rateLimiterConfigs = new RateLimiterNoEvents.Config[](1); - rateLimiterConfigs[0] = SRC_CHAIN_1_RATE_LIMITER_CONFIG; - - uint64[] memory chainSelectors = new uint64[](1); - chainSelectors[0] = SRC_CHAIN_1_SELECTOR; + RATE_LIMITER_CONFIG_1.capacity = RATE_LIMITER_CONFIG_1.capacity * 2; - MultiAggregateRateLimiter.RateLimiterConfigUpdates memory configUpdates = MultiAggregateRateLimiter - .RateLimiterConfigUpdates({chainSelectors: chainSelectors, rateLimiterConfigs: rateLimiterConfigs}); + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.rate); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.capacity); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity / 2, bucket.tokens); + assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); + assertEq(RATE_LIMITER_CONFIG_1.capacity / 2, bucket.tokens); assertEq(BLOCK_TIME, bucket.lastUpdated); uint256 warpTime = 4; vm.warp(BLOCK_TIME + warpTime); - bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.rate); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.capacity); - assertEq( - SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity / 2 + warpTime * SRC_CHAIN_1_RATE_LIMITER_CONFIG.rate, bucket.tokens - ); + assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); + assertEq(RATE_LIMITER_CONFIG_1.capacity / 2 + warpTime * RATE_LIMITER_CONFIG_1.rate, bucket.tokens); assertEq(BLOCK_TIME + warpTime, bucket.lastUpdated); vm.warp(BLOCK_TIME + warpTime * 100); // Bucket overflow - bucket = s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); - assertEq(SRC_CHAIN_1_RATE_LIMITER_CONFIG.capacity, bucket.tokens); + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.tokens); } // Reverts @@ -242,131 +446,604 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe vm.warp(BLOCK_TIME - 1); vm.expectRevert(stdError.arithmeticError); - s_rateLimiter.currentRateLimiterState(SRC_CHAIN_1_SELECTOR); + s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); } } -// /// @notice #setRateLimiterConfig -// contract MultiAggregateRateLimiter_setRateLimiterConfig is MultiAggregateRateLimiterSetup { -// event ConfigChanged(RateLimiter.Config config); +/// @notice #applyRateLimiterConfigUpdates +contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggregateRateLimiterSetup { + function test_ZeroConfigs_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](0); -// function test_Owner_Success() public { -// setConfig(); -// } + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); -// function test_TokenLimitAdmin_Success() public { -// vm.startPrank(ADMIN); -// setConfig(); -// } + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } -// function setConfig() private { -// RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); -// assertEq(s_config.rate, bucket.rate); -// assertEq(s_config.capacity, bucket.capacity); + function test_SingleConfig_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1 + 1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); -// if (bucket.isEnabled) { -// s_config = RateLimiter.Config({isEnabled: false, rate: 0, capacity: 0}); -// } else { -// s_config = RateLimiter.Config({isEnabled: true, rate: 100, capacity: 200}); -// } + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + ); -// vm.expectEmit(); -// emit ConfigChanged(s_config); + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); -// s_rateLimiter.setRateLimiterConfig(s_config); + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); -// bucket = s_rateLimiter.currentRateLimiterState(); -// assertEq(s_config.rate, bucket.rate); -// assertEq(s_config.capacity, bucket.capacity); -// assertEq(s_config.isEnabled, bucket.isEnabled); -// } + RateLimiterNoEvents.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); + assertEq(BLOCK_TIME, bucket1.lastUpdated); + } + + function test_SingleConfigByAdmin_Success() public { + vm.startPrank(ADMIN); + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1 + 1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); -// // Reverts + RateLimiterNoEvents.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); + assertEq(BLOCK_TIME, bucket1.lastUpdated); + } + + function test_MultipleConfigs_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](3); + + for (uint64 i; i < configUpdates.length; ++i) { + configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1 + i + 1, + rateLimiterConfig: RateLimiterNoEvents.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[i].chainSelector, configUpdates[i].rateLimiterConfig + ); + } + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, configUpdates.length); + + for (uint256 i; i < configUpdates.length; ++i) { + RateLimiterNoEvents.TokenBucket memory bucket = + s_rateLimiter.currentRateLimiterState(configUpdates[i].chainSelector); + _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); + assertEq(BLOCK_TIME, bucket.lastUpdated); + } + } -// function test_OnlyOnlyCallableByAdminOrOwner_Revert() public { -// vm.startPrank(STRANGER); + function test_UpdateExistingConfig_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); -// vm.expectRevert(RateLimiter.OnlyCallableByAdminOrOwner.selector); + RateLimiterNoEvents.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); -// s_rateLimiter.setRateLimiterConfig(s_config); -// } -// } + // Capacity equals tokens + assertEq(bucket1.capacity, bucket1.tokens); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + vm.warp(BLOCK_TIME + 1); + bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + assertEq(BLOCK_TIME + 1, bucket1.lastUpdated); + + // Tokens < capacity since capacity doubled + assertTrue(bucket1.capacity != bucket1.tokens); + } + + function test_UpdateExistingConfigWithNoDifference_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + + RateLimiterNoEvents.TokenBucket memory bucketPreUpdate = + s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + vm.warp(BLOCK_TIME + 1); + RateLimiterNoEvents.TokenBucket memory bucketPostUpdate = + s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + _assertTokenBucketEquality(bucketPreUpdate, bucketPostUpdate); + assertEq(BLOCK_TIME + 1, bucketPostUpdate.lastUpdated); + } + + // Reverts + function test_ZeroChainSelector_Revert() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = + MultiAggregateRateLimiter.RateLimiterConfigArgs({chainSelector: 0, rateLimiterConfig: RATE_LIMITER_CONFIG_1}); + + vm.expectRevert(MultiAggregateRateLimiter.ZeroChainSelectorNotAllowed.selector); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + } + + function test_OnlyCallableByAdminOrOwner_Revert() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1 + 1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + vm.startPrank(STRANGER); + + vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + } +} // /// @notice #_rateLimitValue -// contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterSetup { -// event TokensConsumed(uint256 tokens); - -// function test_RateLimitValueSuccess_gas() public { -// vm.pauseGasMetering(); -// // start from blocktime that does not equal rate limiter init timestamp -// vm.warp(BLOCK_TIME + 1); - -// // 15 (tokens) * 4 (price) * 2 (number of times) > 100 (capacity) -// uint256 numberOfTokens = 15; -// uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; - -// vm.expectEmit(); -// emit TokensConsumed(value); - -// vm.resumeGasMetering(); -// s_rateLimiter.rateLimitValue(value); -// vm.pauseGasMetering(); - -// // Get the updated bucket status -// RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); -// // Assert the proper value has been taken out of the bucket -// assertEq(bucket.capacity - value, bucket.tokens); - -// // Since value * 2 > bucket.capacity we cannot take it out twice. -// // Expect a revert when we try, with a wait time. -// uint256 waitTime = 4; -// vm.expectRevert( -// abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) -// ); -// s_rateLimiter.rateLimitValue(value); - -// // Move the block time forward by 10 so the bucket refills by 10 * rate -// vm.warp(BLOCK_TIME + 1 + waitTime); - -// // The bucket has filled up enough so we can take out more tokens -// s_rateLimiter.rateLimitValue(value); -// bucket = s_rateLimiter.currentRateLimiterState(); -// assertEq(bucket.capacity - value + waitTime * s_config.rate - value, bucket.tokens); -// vm.resumeGasMetering(); -// } - -// // Reverts - -// function test_AggregateValueMaxCapacityExceeded_Revert() public { -// RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(); - -// uint256 numberOfTokens = 100; -// uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; - -// vm.expectRevert( -// abi.encodeWithSelector( -// RateLimiter.AggregateValueMaxCapacityExceeded.selector, bucket.capacity, (numberOfTokens * TOKEN_PRICE) / 1e18 -// ) -// ); -// s_rateLimiter.rateLimitValue(value); -// } -// } - -// /// @notice #_getTokenValue -// contract MultiAggregateRateLimiter__getTokenValue is MultiAggregateRateLimiterSetup { -// function test_GetTokenValue_Success() public view { -// uint256 numberOfTokens = 10; -// Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); -// uint256 value = s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); -// assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); -// } - -// // Reverts -// function test_NoTokenPrice_Reverts() public { -// address tokenWithNoPrice = makeAddr("Token with no price"); -// Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); - -// vm.expectRevert(abi.encodeWithSelector(MultiAggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); -// s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); -// } -// } +contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterSetup { + function test_RateLimitValue_Success_gas() public { + vm.pauseGasMetering(); + // start from blocktime that does not equal rate limiter init timestamp + vm.warp(BLOCK_TIME + 1); + + // 15 (tokens) * 4 (price) * 2 (number of times) > 100 (capacity) + uint256 numberOfTokens = 15; + uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, value); + + vm.resumeGasMetering(); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + vm.pauseGasMetering(); + + // Get the updated bucket status + RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + // Assert the proper value has been taken out of the bucket + assertEq(bucket.capacity - value, bucket.tokens); + + // Since value * 2 > bucket.capacity we cannot take it out twice. + // Expect a revert when we try, with a wait time. + uint256 waitTime = 4; + vm.expectRevert( + abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) + ); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + + // Move the block time forward by 10 so the bucket refills by 10 * rate + vm.warp(BLOCK_TIME + 1 + waitTime); + + // The bucket has filled up enough so we can take out more tokens + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + assertEq(bucket.capacity - value + waitTime * RATE_LIMITER_CONFIG_1.rate - value, bucket.tokens); + vm.resumeGasMetering(); + } + + function test_RateLimitValueDifferentChainSelectors_Success() public { + vm.pauseGasMetering(); + // start from blocktime that does not equal rate limiter init timestamp + vm.warp(BLOCK_TIME + 1); + + // 15 (tokens) * 4 (price) * 2 (number of times) > 100 (capacity) + uint256 numberOfTokens = 15; + uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, value); + + vm.resumeGasMetering(); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + vm.pauseGasMetering(); + + // Get the updated bucket status + RateLimiterNoEvents.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiterNoEvents.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + + // Assert the proper value has been taken out of the bucket + assertEq(bucket1.capacity - value, bucket1.tokens); + // CHAIN_SELECTOR_2 should remain unchanged + assertEq(bucket2.capacity, bucket2.tokens); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_2, value); + + vm.resumeGasMetering(); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_2, value); + vm.pauseGasMetering(); + + bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + + assertEq(bucket2.capacity - value, bucket2.tokens); + // CHAIN_SELECTOR_1 should remain unchanged + assertEq(bucket1.capacity - value, bucket1.tokens); + } + + // Reverts + + function test_AggregateValueMaxCapacityExceeded_Revert() public { + RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + + uint256 numberOfTokens = 100; + uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; + + vm.expectRevert( + abi.encodeWithSelector( + RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, + bucket.capacity, + (numberOfTokens * TOKEN_PRICE) / 1e18 + ) + ); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + } +} + +/// @notice #_getTokenValue +contract MultiAggregateRateLimiter__getTokenValue is MultiAggregateRateLimiterSetup { + function test_GetTokenValue_Success() public view { + uint256 numberOfTokens = 10; + Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); + uint256 value = s_rateLimiter.getTokenValue(tokenAmount); + assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); + } + + // Reverts + function test_NoTokenPrice_Reverts() public { + address tokenWithNoPrice = makeAddr("Token with no price"); + Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); + + vm.expectRevert(abi.encodeWithSelector(MultiAggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); + s_rateLimiter.getTokenValue(tokenAmount); + } +} + +/// @notice #updateRateLimitTokens +contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLimiterSetup { + function setUp() public virtual override { + super.setUp(); + + // Clear rate limit tokens state + MultiAggregateRateLimiter.RateLimitToken[] memory remove = + new MultiAggregateRateLimiter.RateLimitToken[](s_sourceTokens.length); + for (uint256 i = 0; i < s_sourceTokens.length; ++i) { + remove[i] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); + } + s_rateLimiter.updateRateLimitTokens(remove, new MultiAggregateRateLimiter.RateLimitToken[](0)); + } + + function test_UpdateRateLimitTokens_Success() public { + MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](2); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); + adds[1] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); + + for (uint256 i = 0; i < adds.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); + } + + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); + + (address[] memory sourceTokens, address[] memory destTokens) = s_rateLimiter.getAllRateLimitTokens(); + + for (uint256 i = 0; i < adds.length; ++i) { + assertEq(adds[i].sourceToken, sourceTokens[i]); + assertEq(adds[i].destToken, destTokens[i]); + } + } + + function test_UpdateRateLimitTokens_AddsAndRemoves_Success() public { + MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](2); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); + adds[1] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); + + MultiAggregateRateLimiter.RateLimitToken[] memory removes = new MultiAggregateRateLimiter.RateLimitToken[](1); + removes[0] = adds[0]; + + for (uint256 i = 0; i < adds.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); + } + + s_rateLimiter.updateRateLimitTokens(removes, adds); + + for (uint256 i = 0; i < removes.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); + } + + s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitToken[](0)); + + (address[] memory sourceTokens, address[] memory destTokens) = s_rateLimiter.getAllRateLimitTokens(); + + assertEq(1, sourceTokens.length); + assertEq(adds[1].sourceToken, sourceTokens[0]); + + assertEq(1, destTokens.length); + assertEq(adds[1].destToken, destTokens[0]); + } + + function test_UpdateRateLimitTokensByAdmin_Success() public { + vm.startPrank(ADMIN); + + MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](2); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); + adds[1] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); + + for (uint256 i = 0; i < adds.length; ++i) { + vm.expectEmit(); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); + } + + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); + + (address[] memory sourceTokens, address[] memory destTokens) = s_rateLimiter.getAllRateLimitTokens(); + + for (uint256 i = 0; i < adds.length; ++i) { + assertEq(adds[i].sourceToken, sourceTokens[i]); + assertEq(adds[i].destToken, destTokens[i]); + } + } + + // Reverts + + function test_ZeroSourceToken_Revert() public { + MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](1); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: address(0), destToken: s_destTokens[0]}); + + vm.expectRevert(MultiAggregateRateLimiter.ZeroAddressNotAllowed.selector); + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); + } + + function test_ZeroDestToken_Revert() public { + MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](1); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_destTokens[0], destToken: address(0)}); + + vm.expectRevert(MultiAggregateRateLimiter.ZeroAddressNotAllowed.selector); + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); + } + + function test_NonOwner_Revert() public { + MultiAggregateRateLimiter.RateLimitToken[] memory addsAndRemoves = new MultiAggregateRateLimiter.RateLimitToken[](4); + + vm.startPrank(STRANGER); + + vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + s_rateLimiter.updateRateLimitTokens(addsAndRemoves, addsAndRemoves); + } +} + +/// @notice #validateIncomingMessage +contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRateLimiterSetup { + address internal immutable MOCK_RECEIVER = address(1113); + + function setUp() public virtual override { + super.setUp(); + + MultiAggregateRateLimiter.RateLimitToken[] memory tokensToAdd = + new MultiAggregateRateLimiter.RateLimitToken[](s_sourceTokens.length); + for (uint224 i = 0; i < s_sourceTokens.length; ++i) { + tokensToAdd[i] = + MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); + + Internal.PriceUpdates memory priceUpdates = + getSingleTokenPriceUpdateStruct(s_destTokens[i], TOKEN_PRICE * (i + 1)); + s_priceRegistry.updatePrices(priceUpdates); + } + s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), tokensToAdd); + } + + function test_ValidateMessageWithNoTokens_Success() public { + vm.startPrank(MOCK_OFFRAMP); + + vm.recordLogs(); + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); + + // No consumed rate limit events + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } + + function test_ValidateMessageWithTokens_Success() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 3}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); + + // 3 tokens * TOKEN_PRICE + 1 token * (2 * TOKEN_PRICE) + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, (5 * TOKEN_PRICE) / 1e18); + + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + function test_ValidateMessageWithDisabledRateLimitToken_Success() public { + MultiAggregateRateLimiter.RateLimitToken[] memory tokensToRemove = new MultiAggregateRateLimiter.RateLimitToken[](1); + tokensToRemove[0] = + MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); + s_rateLimiter.updateRateLimitTokens(tokensToRemove, new MultiAggregateRateLimiter.RateLimitToken[](0)); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 5}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); + + vm.startPrank(MOCK_OFFRAMP); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, (5 * TOKEN_PRICE) / 1e18); + + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + function test_ValidateMessageWithRateLimitDisabled_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + chainSelector: CHAIN_SELECTOR_1, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); + configUpdates[0].rateLimiterConfig.isEnabled = false; + + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 1000}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 50}); + + vm.startPrank(MOCK_OFFRAMP); + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // No consumed rate limit events + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 0); + } + + function test_ValidateMessageWithTokensOnDifferentChains_Success() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 2}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 1}); + + // 2 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) + uint256 totalValue = (4 * TOKEN_PRICE) / 1e18; + + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Chain 1 changed + RateLimiterNoEvents.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 unchanged + RateLimiterNoEvents.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + assertEq(bucketChain2.capacity, bucketChain2.tokens); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_2, (4 * TOKEN_PRICE) / 1e18); + + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); + + // Chain 1 unchanged + bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); + + // Chain 2 changed + bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); + } + + function test_ValidateMessageWithRateLimitReset_Success() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 20}); + + // Remaining capacity: 100 -> 20 + uint256 totalValue = (20 * TOKEN_PRICE) / 1e18; + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) + vm.expectRevert(abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 12, 20)); + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Remaining capacity: 20 -> 35 (need to wait 9 more blocks) + vm.warp(BLOCK_TIME + 3); + vm.expectRevert(abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 9, 35)); + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + + // Remaining capacity: 35 -> 80 (can fit exactly 80) + vm.warp(BLOCK_TIME + 12); + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + // Reverts + + function test_ValidateMessageWithRateLimitExceeded_Revert() public { + vm.startPrank(MOCK_OFFRAMP); + + Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); + tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 80}); + tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 30}); + + uint256 totalValue = (80 * TOKEN_PRICE + 2 * (30 * TOKEN_PRICE)) / 1e18; + vm.expectRevert( + abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, 100, totalValue) + ); + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + } + + function test_ValidateMessageFromUnauthorizedCaller_Revert() public { + vm.startPrank(STRANGER); + + vm.expectRevert(abi.encodeWithSelector(MultiAggregateRateLimiter.UnauthorizedCaller.selector, STRANGER)); + s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); + } + + function _generateAny2EVMMessageNoTokens(uint64 sourceChainSelector) + internal + pure + returns (Client.Any2EVMMessage memory) + { + return _generateAny2EVMMessage(sourceChainSelector, new Client.EVMTokenAmount[](0)); + } + + function _generateAny2EVMMessage( + uint64 sourceChainSelector, + Client.EVMTokenAmount[] memory tokenAmounts + ) internal pure returns (Client.Any2EVMMessage memory) { + return Client.Any2EVMMessage({ + messageId: keccak256(bytes("messageId")), + sourceChainSelector: sourceChainSelector, + sender: abi.encode(OWNER), + data: abi.encode(0), + destTokenAmounts: tokenAmounts + }); + } +} diff --git a/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol index 5a33b437c7..04e4209fb0 100644 --- a/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol @@ -22,6 +22,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { error PriceNotFoundForToken(address token); error UpdateLengthMismatch(); error ZeroAddressNotAllowed(); + error ZeroChainSelectorNotAllowed(); event RateLimiterConfigUpdated(uint64 indexed chainSelector, RateLimiterNoEvents.Config config); event RateLimiterTokensConsumed(uint64 indexed chainSelector, uint256 tokens); @@ -58,10 +59,10 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Rate limiter token bucket states per chain mapping(uint64 chainSelector => RateLimiterNoEvents.TokenBucket rateLimiter) s_rateLimitersByChainSelector; - /// @notice A collection of rate limiter configuration updates - struct RateLimiterConfigUpdates { - uint64[] chainSelectors; - RateLimiterNoEvents.Config[] rateLimiterConfigs; + /// @notice Update args for a single rate limiter config update + struct RateLimiterConfigArgs { + uint64 chainSelector; // Chain selector to set config for + RateLimiterNoEvents.Config rateLimiterConfig; // Rate limiter config to set } /// @param rateLimiterConfigs The RateLimiterNoEvents.Configs per chain containing the capacity and refill rate @@ -70,7 +71,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @param priceRegistry the price registry to set /// @param authorizedCallers the authorized callers to set constructor( - RateLimiterConfigUpdates memory rateLimiterConfigs, + RateLimiterConfigArgs[] memory rateLimiterConfigs, address admin, address priceRegistry, address[] memory authorizedCallers @@ -133,21 +134,21 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Applies the provided rate limiter config updates. /// @param rateLimiterUpdates Rate limiter updates /// @dev should only be callable by the owner or token limit admin - function applyRateLimiterConfigUpdates(RateLimiterConfigUpdates memory rateLimiterUpdates) external onlyAdminOrOwner { + function applyRateLimiterConfigUpdates(RateLimiterConfigArgs[] memory rateLimiterUpdates) external onlyAdminOrOwner { _applyRateLimiterConfigUpdates(rateLimiterUpdates); } /// @notice Applies the provided rate limiter config updates. /// @param rateLimiterUpdates Rate limiter updates - function _applyRateLimiterConfigUpdates(RateLimiterConfigUpdates memory rateLimiterUpdates) internal { - uint256 updateLength = rateLimiterUpdates.chainSelectors.length; - if (updateLength != rateLimiterUpdates.rateLimiterConfigs.length) { - revert UpdateLengthMismatch(); - } - - for (uint256 i = 0; i < updateLength; ++i) { - RateLimiterNoEvents.Config memory configUpdate = rateLimiterUpdates.rateLimiterConfigs[i]; - uint64 chainSelector = rateLimiterUpdates.chainSelectors[i]; + function _applyRateLimiterConfigUpdates(RateLimiterConfigArgs[] memory rateLimiterUpdates) internal { + for (uint256 i = 0; i < rateLimiterUpdates.length; ++i) { + RateLimiterConfigArgs memory updateArgs = rateLimiterUpdates[i]; + RateLimiterNoEvents.Config memory configUpdate = updateArgs.rateLimiterConfig; + uint64 chainSelector = updateArgs.chainSelector; + + if (chainSelector == 0) { + revert ZeroChainSelectorNotAllowed(); + } RateLimiterNoEvents.TokenBucket memory tokenBucket = s_rateLimitersByChainSelector[chainSelector]; uint32 lastUpdated = tokenBucket.lastUpdated; @@ -199,12 +200,24 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } for (uint256 i = 0; i < adds.length; ++i) { - if (s_rateLimitedTokensDestToSource.set(adds[i].destToken, adds[i].sourceToken)) { - emit TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); + address destToken = adds[i].destToken; + address sourceToken = adds[i].sourceToken; + + if (destToken == address(0) || sourceToken == address(0)) { + revert ZeroAddressNotAllowed(); + } + + if (s_rateLimitedTokensDestToSource.set(destToken, sourceToken)) { + emit TokenAggregateRateLimitAdded(sourceToken, destToken); } } } + /// @return priceRegistry The configured PriceRegistry address + function getPriceRegistry() external view returns (address) { + return s_priceRegistry; + } + /// @notice Sets the Price Registry address /// @param newPriceRegistry the address of the new PriceRegistry /// @dev precondition The address must be a non-zero address @@ -228,6 +241,12 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { // │ Access │ // ================================================================ + /// @param caller Address to check whether it is an authorized caller + /// @return flag whether the caller is an authorized caller + function isAuthorizedCaller(address caller) external view returns (bool) { + return s_authorizedCallers[caller]; + } + /// @notice Updates the callers that are authorized to call the message validation functions /// @param authorizedCallerArgs Callers to add and remove function applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) external onlyAdminOrOwner { @@ -253,9 +272,10 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { for (uint256 i; i < removedCallers.length; ++i) { address caller = removedCallers[i]; - delete s_authorizedCallers[caller]; - // TODO: only emit if value was present - emit AuthorizedCallerRemoved(caller); + if (s_authorizedCallers[caller]) { + delete s_authorizedCallers[caller]; + emit AuthorizedCallerRemoved(caller); + } } } diff --git a/tools/ci/ccip_lcov_prune b/tools/ci/ccip_lcov_prune index f3c494fc0c..23145e827b 100755 --- a/tools/ci/ccip_lcov_prune +++ b/tools/ci/ccip_lcov_prune @@ -28,5 +28,4 @@ lcov --remove $1 -o $2 \ 'src/v0.8/ccip/applications/CCIPClientExample.sol' \ 'src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol' \ 'src/v0.8/ccip/onRamp/EVM2EVMMultiOnRamp.sol' \ - 'src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol' \ --rc lcov_branch_coverage=1 From 08415374e9ff2a9043f015a3d5ce5170f52b6212 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Thu, 23 May 2024 14:10:18 +0200 Subject: [PATCH 10/23] chore: create wrappers, snapshot & changesets --- .changeset/few-spies-march.md | 5 + contracts/.changeset/modern-bees-hear.md | 5 + contracts/gas-snapshots/ccip.gas-snapshot | 281 ++-- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 2 - .../MultiAggregateRateLimiter.t.sol | 1 - .../evm_2_evm_multi_offramp.go | 1384 ++++------------- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 473 insertions(+), 1207 deletions(-) create mode 100644 .changeset/few-spies-march.md create mode 100644 contracts/.changeset/modern-bees-hear.md diff --git a/.changeset/few-spies-march.md b/.changeset/few-spies-march.md new file mode 100644 index 0000000000..0bf059fcfb --- /dev/null +++ b/.changeset/few-spies-march.md @@ -0,0 +1,5 @@ +--- +"ccip": minor +--- + +#changed Implement hook-based multi-aggregate rate limiter diff --git a/contracts/.changeset/modern-bees-hear.md b/contracts/.changeset/modern-bees-hear.md new file mode 100644 index 0000000000..9af96f4e4d --- /dev/null +++ b/contracts/.changeset/modern-bees-hear.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts-ccip": minor +--- + +#changed Implement hook-based multi-aggregate rate limiter diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index cf86c2c3f8..fcb92ffeba 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -66,110 +66,114 @@ CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) DefensiveExampleTest:test_Recovery() (gas: 424253) E2E:test_E2E_3MessagesSuccess_gas() (gas: 1058957) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 409685) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 145611) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12420) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 409655) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 145631) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12398) EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_CommitStoreAlreadyInUse_Revert() (gas: 45053) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_CommitStoreMismatchingOnRamp_Revert() (gas: 45088) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRampAndPrevOffRamp_Revert() (gas: 140669) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 140358) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainPrevOffRamp_Revert() (gas: 140528) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 133961) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 63990) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13026) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 286471) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 231876) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 157405) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 184950) -EVM2EVMMultiOffRamp_batchExecute:test_Paused_Revert() (gas: 125217) -EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 142242) -EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 526949) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_CommitStoreMismatchingOnRamp_Revert() (gas: 45066) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRampAndPrevOffRamp_Revert() (gas: 140644) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 140355) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainPrevOffRamp_Revert() (gas: 140503) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 133936) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 63968) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13004) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 286885) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 232312) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 157565) +EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 185248) +EVM2EVMMultiOffRamp_batchExecute:test_Paused_Revert() (gas: 125195) +EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 142358) +EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 490499) EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10447) -EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 17138) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5969142) -EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144277) -EVM2EVMMultiOffRamp_execute:test_DisabledSourceChain_Revert() (gas: 37423) -EVM2EVMMultiOffRamp_execute:test_EmptyReport_Revert() (gas: 21734) -EVM2EVMMultiOffRamp_execute:test_InvalidMessageId_Revert() (gas: 41735) -EVM2EVMMultiOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 451620) -EVM2EVMMultiOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 51703) -EVM2EVMMultiOffRamp_execute:test_MessageTooLarge_Revert() (gas: 160327) -EVM2EVMMultiOffRamp_execute:test_MismatchingOnRampAddress_Revert() (gas: 44560) -EVM2EVMMultiOffRamp_execute:test_MismatchingSourceChainSelector_Revert() (gas: 41649) -EVM2EVMMultiOffRamp_execute:test_NonExistingSourceChain_Revert() (gas: 37638) -EVM2EVMMultiOffRamp_execute:test_Paused_Revert() (gas: 123176) -EVM2EVMMultiOffRamp_execute:test_ReceiverError_Success() (gas: 176646) -EVM2EVMMultiOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 189942) -EVM2EVMMultiOffRamp_execute:test_RootNotCommitted_Revert() (gas: 46468) -EVM2EVMMultiOffRamp_execute:test_RouterYULCall_Revert() (gas: 412640) -EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokensOtherChain_Success() (gas: 241122) -EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 188677) -EVM2EVMMultiOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 257609) -EVM2EVMMultiOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 125233) -EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 395653) -EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 62202) -EVM2EVMMultiOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 59646) -EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 535666) -EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 473193) -EVM2EVMMultiOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35823) -EVM2EVMMultiOffRamp_execute:test_UnhealthySingleChainCurse_Revert() (gas: 525352) -EVM2EVMMultiOffRamp_execute:test_Unhealthy_Revert() (gas: 522937) -EVM2EVMMultiOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 71735) -EVM2EVMMultiOffRamp_execute:test_WithCurseOnAnotherSourceChain_Success() (gas: 490127) -EVM2EVMMultiOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 155593) -EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20638) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 258998) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20220) -EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 193038) -EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48744) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48251) -EVM2EVMMultiOffRamp_execute_upgrade:test_NoPrevOffRampForChain_Success() (gas: 247691) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 247409) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 299590) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 280074) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249177) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237259) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedWithMultiRamp_Revert() (gas: 6174587) -EVM2EVMMultiOffRamp_execute_upgrade:test_Upgraded_Success() (gas: 142578) -EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3607928) -EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118398) -EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87335) -EVM2EVMMultiOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 503492) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 205538) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 28244) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchMultipleReports_Revert() (gas: 160660) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 79950) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 28720) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 208307) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithMultiReportGasOverride_Success() (gas: 652700) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithPartialMessages_Success() (gas: 295113) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 207711) -EVM2EVMMultiOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2338131) +EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 17112) +EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5028941) +EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 97599) +EVM2EVMMultiOffRamp_execute:test_DisabledSourceChain_Revert() (gas: 37356) +EVM2EVMMultiOffRamp_execute:test_EmptyReport_Revert() (gas: 21645) +EVM2EVMMultiOffRamp_execute:test_InvalidMessageId_Revert() (gas: 41668) +EVM2EVMMultiOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 424633) +EVM2EVMMultiOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 51679) +EVM2EVMMultiOffRamp_execute:test_MessageTooLarge_Revert() (gas: 160305) +EVM2EVMMultiOffRamp_execute:test_MismatchingOnRampAddress_Revert() (gas: 44471) +EVM2EVMMultiOffRamp_execute:test_MismatchingSourceChainSelector_Revert() (gas: 41560) +EVM2EVMMultiOffRamp_execute:test_NonExistingSourceChain_Revert() (gas: 37615) +EVM2EVMMultiOffRamp_execute:test_Paused_Revert() (gas: 123154) +EVM2EVMMultiOffRamp_execute:test_ReceiverError_Success() (gas: 176721) +EVM2EVMMultiOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 190038) +EVM2EVMMultiOffRamp_execute:test_RootNotCommitted_Revert() (gas: 46401) +EVM2EVMMultiOffRamp_execute:test_RouterYULCall_Revert() (gas: 412264) +EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokensOtherChain_Success() (gas: 241243) +EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 188797) +EVM2EVMMultiOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 257520) +EVM2EVMMultiOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 125326) +EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 366689) +EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 62113) +EVM2EVMMultiOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 59579) +EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 499083) +EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 436654) +EVM2EVMMultiOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35734) +EVM2EVMMultiOffRamp_execute:test_UnhealthySingleChainCurse_Revert() (gas: 488746) +EVM2EVMMultiOffRamp_execute:test_Unhealthy_Revert() (gas: 486353) +EVM2EVMMultiOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 71668) +EVM2EVMMultiOffRamp_execute:test_WithCurseOnAnotherSourceChain_Success() (gas: 453588) +EVM2EVMMultiOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 155597) +EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20641) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 229960) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20268) +EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 181672) +EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50926) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 50414) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 158010) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 264324) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 156820) +EVM2EVMMultiOffRamp_execute_upgrade:test_NoPrevOffRampForChain_Success() (gas: 247688) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 247477) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 299662) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 279986) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249085) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237145) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedWithMultiRamp_Revert() (gas: 5057060) +EVM2EVMMultiOffRamp_execute_upgrade:test_Upgraded_Success() (gas: 142645) +EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3591010) +EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118288) +EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87181) +EVM2EVMMultiOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 503772) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 205866) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 28178) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchMultipleReports_Revert() (gas: 160374) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 79774) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 28654) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 208587) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithMultiReportGasOverride_Success() (gas: 654429) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithPartialMessages_Success() (gas: 295713) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 208013) +EVM2EVMMultiOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2318022) EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnOnRampAddress_Success() (gas: 10983) EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnSourceChain_Success() (gas: 11036) -EVM2EVMMultiOffRamp_metadataHash:test_MetadataHash_Success() (gas: 9146) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 139128) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 163216) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAContract_Reverts() (gas: 32041) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 28420) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 64933) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 50982) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 70747) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 196135) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 150585) -EVM2EVMMultiOffRamp_report:test_IncorrectArrayType_Revert() (gas: 10026) -EVM2EVMMultiOffRamp_report:test_LargeBatch_Success() (gas: 1489143) -EVM2EVMMultiOffRamp_report:test_MultipleReports_Success() (gas: 232122) -EVM2EVMMultiOffRamp_report:test_NonArray_Revert() (gas: 22751) -EVM2EVMMultiOffRamp_report:test_SingleReport_Success() (gas: 139874) -EVM2EVMMultiOffRamp_report:test_ZeroReports_Revert() (gas: 9850) -EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40324) -EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38510) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141645) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 208833) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 217490) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 312612) -EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 291597) +EVM2EVMMultiOffRamp_metadataHash:test_MetadataHash_Success() (gas: 9169) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 151908) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAContract_Reverts() (gas: 32046) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 28422) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 64901) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 50943) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 70763) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 167094) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 121533) +EVM2EVMMultiOffRamp_report:test_IncorrectArrayType_Revert() (gas: 9982) +EVM2EVMMultiOffRamp_report:test_LargeBatch_Success() (gas: 1494774) +EVM2EVMMultiOffRamp_report:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 385109) +EVM2EVMMultiOffRamp_report:test_MultipleReports_Success() (gas: 232704) +EVM2EVMMultiOffRamp_report:test_NonArray_Revert() (gas: 22752) +EVM2EVMMultiOffRamp_report:test_SingleReport_Success() (gas: 140039) +EVM2EVMMultiOffRamp_report:test_ZeroReports_Revert() (gas: 9894) +EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 38184) +EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38497) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 117401) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 139471) +EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 197414) +EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 206005) +EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 282919) +EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 262652) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16208) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigNewPrevOnRampOnExistingChain_Revert() (gas: 29352) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput() (gas: 12405) @@ -453,20 +457,55 @@ MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60758) MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126294) MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63302) MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 43853) -MultiAggregateRateLimiter__getTokenValue:test_GetTokenValue_Success() (gas: 19623) -MultiAggregateRateLimiter__getTokenValue:test_NoTokenPrice_Reverts() (gas: 21208) -MultiAggregateRateLimiter__rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16403) -MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 26920) -MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19691) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 40911) -MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15353) -MultiAggregateRateLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -MultiAggregateRateLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13047) -MultiAggregateRateLimiter_setAdmin:test_Owner_Success() (gas: 18989) -MultiAggregateRateLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17479) -MultiAggregateRateLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30062) -MultiAggregateRateLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32071) +MultiAggregateRateLimiter__getTokenValue:test_GetTokenValue_Success() (gas: 19632) +MultiAggregateRateLimiter__getTokenValue:test_NoTokenPrice_Reverts() (gas: 21221) +MultiAggregateRateLimiter__rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16940) +MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValueDifferentChainSelectors_Success() (gas: 9223372036854754743) +MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValue_Success_gas() (gas: 18930) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 188570) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByAdminOrOwner_Revert() (gas: 19288) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigByAdmin_Success() (gas: 77318) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 74783) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 35690) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 37574) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 16890) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12353) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1949294) +MultiAggregateRateLimiter_constructor:test_ConstructorNoConfigs_Success() (gas: 1999748) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2118549) +MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 20062) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 44944) +MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15672) +MultiAggregateRateLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10553) +MultiAggregateRateLimiter_setAdmin:test_Admin_Success() (gas: 19485) +MultiAggregateRateLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13037) +MultiAggregateRateLimiter_setAdmin:test_Owner_Success() (gas: 19039) +MultiAggregateRateLimiter_setAuthorizedCallers:test_AddAndRemove_Success() (gas: 75740) +MultiAggregateRateLimiter_setAuthorizedCallers:test_AddThenRemove_Success() (gas: 30978) +MultiAggregateRateLimiter_setAuthorizedCallers:test_ChangedByAdmin_Success() (gas: 18091) +MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyAdd_Success() (gas: 68891) +MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyOwnerOrAdmin_Revert() (gas: 15326) +MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyRemove_Success() (gas: 18648) +MultiAggregateRateLimiter_setAuthorizedCallers:test_SkipRemove_Success() (gas: 17707) +MultiAggregateRateLimiter_setAuthorizedCallers:test_ZeroAddressAdd_Revert() (gas: 12646) +MultiAggregateRateLimiter_setPriceRegistry:test_Admin_Success() (gas: 21492) +MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwnerOrAdmin_Revert() (gas: 13016) +MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19024) +MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10562) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18880) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensByAdmin_Success() (gas: 201288) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 161248) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_Success() (gas: 198751) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 17207) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 17262) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14428) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 64621) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithNoTokens_Success() (gas: 15140) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 66380) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50047) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 77710) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 88029) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithTokens_Success() (gas: 54987) MultiCommitStore_applySourceChainConfigUpdates:test_InvalidSourceChainConfig_Revert() (gas: 29592) MultiCommitStore_applySourceChainConfigUpdates:test_OnlyOwner_Revert() (gas: 12743) MultiCommitStore_constructor:test_Constructor_Failure() (gas: 316394) @@ -623,6 +662,20 @@ RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 275862) RMN_voteToCurse:test_InvalidVoter_Revert() (gas: 13671) RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 194189) RMN_voteToCurse:test_VoteToCurseSuccess_gas() (gas: 70265) +RateLimiterNoEvents_constructor:test_Constructor_Success() (gas: 19585) +RateLimiterNoEvents_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 15837) +RateLimiterNoEvents_consume:test_AggregateValueRateLimitReached_Revert() (gas: 21074) +RateLimiterNoEvents_consume:test_ConsumeAggregateValue_Success() (gas: 28738) +RateLimiterNoEvents_consume:test_ConsumeTokens_Success() (gas: 15351) +RateLimiterNoEvents_consume:test_ConsumeUnlimited_Success() (gas: 36730) +RateLimiterNoEvents_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15642) +RateLimiterNoEvents_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 22954) +RateLimiterNoEvents_consume:test_Refill_Success() (gas: 32145) +RateLimiterNoEvents_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18171) +RateLimiterNoEvents_consume:test_TokenRateLimitReached_Revert() (gas: 23552) +RateLimiterNoEvents_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 36843) +RateLimiterNoEvents_currentTokenBucketState:test_Refill_Success() (gas: 44480) +RateLimiterNoEvents_setTokenBucketConfig:test_SetRateLimiterNoEventsConfig_Success() (gas: 33866) RateLimiter_constructor:test_Constructor_Success() (gas: 19650) RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 15916) RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22222) diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 5277807c92..8fea06f904 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -22,8 +22,6 @@ import {OCR2BaseNoChecks} from "../ocr/OCR2BaseNoChecks.sol"; import {ERC165Checker} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/ERC165Checker.sol"; -import {console} from "forge-std/console.sol"; - /// @notice EVM2EVMOffRamp enables OCR networks to execute multiple messages /// in an OffRamp in a single transaction. /// @dev The EVM2EVMOnRamp, CommitStore and EVM2EVMOffRamp form an xchain upgradeable unit. Any change to one of them diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 0919330c06..6f48a470f1 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -986,7 +986,6 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 20}); // Remaining capacity: 100 -> 20 - uint256 totalValue = (20 * TOKEN_PRICE) / 1e18; s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go index f0441eb70d..2a82589626 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go @@ -46,15 +46,10 @@ type ClientEVMTokenAmount struct { type EVM2EVMMultiOffRampDynamicConfig struct { PermissionLessExecutionThresholdSeconds uint32 Router common.Address - PriceRegistry common.Address MaxNumberOfTokensPerMsg uint16 MaxDataBytes uint32 MaxPoolReleaseOrMintGas uint32 -} - -type EVM2EVMMultiOffRampRateLimitToken struct { - SourceToken common.Address - DestToken common.Address + MessageValidator common.Address } type EVM2EVMMultiOffRampSourceChainConfig struct { @@ -101,30 +96,16 @@ type InternalExecutionReportSingleChain struct { ProofFlagBits *big.Int } -type RateLimiterConfig struct { - IsEnabled bool - Capacity *big.Int - Rate *big.Int -} - -type RateLimiterTokenBucket struct { - Tokens *big.Int - LastUpdated uint32 - IsEnabled bool - Capacity *big.Int - Rate *big.Int -} - var EVM2EVMMultiOffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"InvalidMessageId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedSenderWithPreviousRampMessageInflight\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"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\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"sourceTokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"destTokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenLimitAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"setAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setOCR2Config\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"setRateLimiterConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.RateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"destToken\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.RateLimitToken[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200729538038062007295833981016040819052620000359162000771565b8033806000816200008d5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000c057620000c081620001b5565b50506040805160a081018252602084810180516001600160801b039081168085524263ffffffff169385018490528751151585870181905292518216606086018190529790950151166080938401819052600380546001600160a01b031916909517600160801b9384021760ff60a01b1916600160a01b909202919091179093559091029092176004555046905282516001600160a01b031662000177576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160a01b0390811660a05260208401516001600160401b031660c05260408401511660e052620001ac8262000260565b5050506200095e565b336001600160a01b038216036200020f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000084565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015620005c3576000828281518110620002845762000284620008f1565b60200260200101519050600081600001519050806001600160401b0316600003620002ce5760405163c39a620560e01b81526001600160401b038216600482015260240162000084565b60608201516001600160a01b0316620002fa576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600f6020526040902060018101546001600160a01b0316620004c25760a0516040516374eb454760e11b81526001600160401b03841660048201526000916001600160a01b03169063e9d68a8e90602401606060405180830381865afa15801562000378573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200039e919062000907565b905083606001516001600160a01b031681604001516001600160a01b0316141580620003d6575060208101516001600160401b031615155b15620004015760405163c39a620560e01b81526001600160401b038416600482015260240162000084565b620004388385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3620005c760201b60201c565b600283015560608401516001830180546001600160a01b0319166001600160a01b039283161790556040808601518454610100600160a81b0319166101009190931602919091178355516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a15062000529565b606083015160018201546001600160a01b039081169116141580620004fe57506040830151815461010090046001600160a01b03908116911614155b15620005295760405163c39a620560e01b81526001600160401b038316600482015260240162000084565b6020830151815490151560ff199091161781556040516001600160401b038316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af079278490620005ac908490815460ff81161515825260081c6001600160a01b0390811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a250505080600101905062000263565b5050565b60c05160408051602081018490526001600160401b0380871692820192909252911660608201526001600160a01b038316608082015260009060a0016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200065d576200065d62000622565b60405290565b604051608081016001600160401b03811182821017156200065d576200065d62000622565b604051601f8201601f191681016001600160401b0381118282101715620006b357620006b362000622565b604052919050565b80516001600160a01b0381168114620006d357600080fd5b919050565b80516001600160401b0381168114620006d357600080fd5b80518015158114620006d357600080fd5b80516001600160801b0381168114620006d357600080fd5b6000606082840312156200072c57600080fd5b6200073662000638565b90506200074382620006f0565b8152620007536020830162000701565b6020820152620007666040830162000701565b604082015292915050565b600080600083850360e08112156200078857600080fd5b6060808212156200079857600080fd5b620007a262000638565b9150620007af86620006bb565b82526020620007c0818801620006d8565b818401526040620007d460408901620006bb565b604085015260608801519396506001600160401b0380851115620007f757600080fd5b848901945089601f8601126200080c57600080fd5b84518181111562000821576200082162000622565b62000831848260051b0162000688565b818152848101925060079190911b86018401908b8211156200085257600080fd5b958401955b81871015620008cf576080878d031215620008725760008081fd5b6200087c62000663565b6200088788620006d8565b815262000896868901620006f0565b86820152620008a7858901620006bb565b85820152620008b8878901620006bb565b818801528352608096909601959184019162000857565b80985050505050505050620008e8856080860162000719565b90509250925092565b634e487b7160e01b600052603260045260246000fd5b6000606082840312156200091a57600080fd5b6200092462000638565b6200092f83620006f0565b81526200093f60208401620006d8565b60208201526200095260408401620006bb565b60408201529392505050565b60805160a05160c05160e0516168b7620009de6000396000818161023601528181611d7e0152612e7301526000818161020601528181611d5501526138e10152600081816101ca01528181611d27015281816121290152613168015260008181610bba01528181610c06015281816113ec015261143801526168b76000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c806381ff7048116100e3578063b1dc65a41161008c578063f077b59211610066578063f077b592146106ca578063f2fde38b146106e0578063f52121a5146106f357600080fd5b8063b1dc65a4146105b2578063c92b2832146105c5578063e9d68a8e146105d857600080fd5b80638b364334116100bd5780638b364334146105485780638da5cb5b14610574578063afcb95d71461059257600080fd5b806381ff7048146104f757806385572ffb14610527578063873504d71461053557600080fd5b80635e36480c116101455780637437ff9f1161011f5780637437ff9f146103e557806379ba5097146104dc5780637f63b711146104e457600080fd5b80635e36480c1461039d578063666cab8d146103bd578063704b6c02146103d257600080fd5b8063542625af11610176578063542625af146102e7578063546719cd146102fa578063599f64311461035e57600080fd5b806306285c691461019d578063181f5a77146102895780631ef38174146102d2575b600080fd5b610273604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102809190614bbe565b60405180910390f35b6102c56040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b6040516102809190614c71565b6102e56102e0366004614f4f565b610706565b005b6102e56102f5366004615515565b610bb7565b610302610ddf565b604051610280919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610280565b6103b06103ab366004615640565b610e94565b60405161028091906156e3565b6103c5610f28565b6040516102809190615743565b6102e56103e0366004615756565b610f97565b6104cf6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c081018252600a5463ffffffff808216835273ffffffffffffffffffffffffffffffffffffffff64010000000090920482166020840152600b549182169383019390935261ffff7401000000000000000000000000000000000000000082041660608301527601000000000000000000000000000000000000000000008104831660808301527a010000000000000000000000000000000000000000000000000000900490911660a082015290565b6040516102809190615773565b6102e5611087565b6102e56104f23660046157e2565b611184565b6007546005546040805163ffffffff80851682526401000000009094049093166020840152820152606001610280565b6102e56101983660046158c6565b6102e5610543366004615992565b611198565b61055b6105563660046159f6565b611380565b60405167ffffffffffffffff9091168152602001610280565b60005473ffffffffffffffffffffffffffffffffffffffff16610378565b604080516001815260006020820181905291810191909152606001610280565b6102e56105c0366004615a69565b611396565b6102e56105d3366004615b6e565b611627565b61067a6105e6366004615bbe565b6040805160808101825260008082526020820181905291810182905260608101919091525067ffffffffffffffff166000908152600f60209081526040918290208251608081018452815460ff81161515825273ffffffffffffffffffffffffffffffffffffffff610100909104811693820193909352600182015490921692820192909252600290910154606082015290565b6040805182511515815260208084015173ffffffffffffffffffffffffffffffffffffffff9081169183019190915283830151169181019190915260609182015191810191909152608001610280565b6106d26116a9565b604051610280929190615bdb565b6102e56106ee366004615756565b611802565b6102e5610701366004615c00565b611813565b84518460ff16601f82111561077c576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f6f206d616e79207472616e736d697474657273000000000000000000000060448201526064015b60405180910390fd5b806000036107e6576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610773565b6107ee611ade565b6107f785611b61565b60095460005b8181101561087b57600860006009838154811061081c5761081c615c5a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016107fd565b50875160005b81811015610a715760008a828151811061089d5761089d615c5a565b60200260200101519050600060028111156108ba576108ba615679565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260086020526040902054610100900460ff1660028111156108f9576108f9615679565b14610960576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610773565b73ffffffffffffffffffffffffffffffffffffffff81166109ad576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526008602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001617610100836002811115610a5d57610a5d615679565b021790555090505050806001019050610881565b508851610a859060099060208c0190614b28565b506006805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908b161717905560078054610b0b914691309190600090610add9063ffffffff16615cb8565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168d8d8d8d8d8d611ddc565b6005600001819055506000600760049054906101000a900463ffffffff16905043600760046101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600560000154600760009054906101000a900463ffffffff168e8e8e8e8e8e604051610ba299989796959493929190615cdb565b60405180910390a15050505050505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610c42576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff46166024820152604401610773565b815181518114610c7e576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610dcf576000848281518110610c9d57610c9d615c5a565b60200260200101519050600081602001515190506000858481518110610cc557610cc5615c5a565b6020026020010151905080518214610d09576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610dc0576000828281518110610d2857610d28615c5a565b6020026020010151905080600014158015610d63575084602001518281518110610d5457610d54615c5a565b60200260200101516080015181105b15610db75784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810183905260448101829052606401610773565b50600101610d0c565b50505050806001019050610c81565b50610dda8383611e87565b505050565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526040805160a0810182526003546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff161515938301939093526004548084166060840152049091166080820152610e8f90611f30565b905090565b6000610ea260016004615d71565b6002610eaf608085615db3565b67ffffffffffffffff16610ec39190615dda565b67ffffffffffffffff8516600090815260116020526040812090610ee8608087615df1565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c166003811115610f1f57610f1f615679565b90505b92915050565b60606009805480602002602001604051908101604052809291908181526020018280548015610f8d57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610f62575b5050505050905090565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590610fd7575060025473ffffffffffffffffffffffffffffffffffffffff163314155b1561100e576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c9060200160405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff163314611108576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610773565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61118c611ade565b61119581611fe2565b50565b6111a0611ade565b60005b8251811015611280576111dd8382815181106111c1576111c1615c5a565b602002602001015160200151600c61249390919063ffffffff16565b15611278577fcbf3cbeaed4ac1d605ed30f4af06c35acaeff2379db7f6146c9cceee83d5878283828151811061121557611215615c5a565b60200260200101516000015184838151811061123357611233615c5a565b60200260200101516020015160405161126f92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60405180910390a15b6001016111a3565b5060005b8151811015610dda576112dd8282815181106112a2576112a2615c5a565b6020026020010151602001518383815181106112c0576112c0615c5a565b602002602001015160000151600c6124b59092919063ffffffff16565b15611378577ffc23abf7ddbd3c02b1420dafa2355c56c1a06fbb8723862ac14d6bd74177361a82828151811061131557611315615c5a565b60200260200101516000015183838151811061133357611333615c5a565b60200260200101516020015160405161136f92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60405180910390a15b600101611284565b60008061138d84846124e2565b50949350505050565b6113a08787612612565b6005548835908082146113e9576040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610773565b467f00000000000000000000000000000000000000000000000000000000000000001461146a576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610773565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526008602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156114f2576114f2615679565b600281111561150357611503615679565b905250905060028160200151600281111561152057611520615679565b14801561156757506009816000015160ff168154811061154257611542615c5a565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b61159d576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006115ab856020615dda565b6115b6886020615dda565b6115c28b610144615e18565b6115cc9190615e18565b6115d69190615e18565b905036811461161a576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610773565b5050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590611667575060025473ffffffffffffffffffffffffffffffffffffffff163314155b1561169e576040517ff6cd562000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611195600382612659565b6060806116b6600c61283e565b67ffffffffffffffff8111156116ce576116ce614c84565b6040519080825280602002602001820160405280156116f7578160200160208202803683370190505b509150611704600c61283e565b67ffffffffffffffff81111561171c5761171c614c84565b604051908082528060200260200182016040528015611745578160200160208202803683370190505b50905060005b611755600c61283e565b8110156117fd5760008061176a600c84612849565b915091508085848151811061178157611781615c5a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050818484815181106117ce576117ce615c5a565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152505060010161174b565b509091565b61180a611ade565b61119581612865565b33301461184c576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281611889565b60408051808201909152600080825260208201528152602001906001900390816118625790505b506101408401515190915015611942576101408301516040805160608101909152602085015173ffffffffffffffffffffffffffffffffffffffff16608082015261193f91908060a08101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252875167ffffffffffffffff1660208301528781015173ffffffffffffffffffffffffffffffffffffffff169101526101608601518561295a565b90505b6101208301515115801561195857506080830151155b8061197c5750604083015173ffffffffffffffffffffffffffffffffffffffff163b155b806119c9575060408301516119c79073ffffffffffffffffffffffffffffffffffffffff167f85572ffb00000000000000000000000000000000000000000000000000000000612d6d565b155b156119d357505050565b600a546000908190640100000000900473ffffffffffffffffffffffffffffffffffffffff16633cf97983611a088786612d89565b611388886080015189604001516040518563ffffffff1660e01b8152600401611a349493929190615e7d565b6000604051808303816000875af1158015611a53573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a999190810190615f94565b509150915081611ad757806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107739190614c71565b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611b5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610773565b565b600081806020019051810190611b779190616002565b602081015190915073ffffffffffffffffffffffffffffffffffffffff16611bcb576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600a805460208085015173ffffffffffffffffffffffffffffffffffffffff908116640100000000027fffffffffffffffff00000000000000000000000000000000000000000000000090931663ffffffff9586161792909217909255604080850151600b805460608089015160808a015160a08b01518a167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff91909a1676010000000000000000000000000000000000000000000002167fffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffff61ffff90921674010000000000000000000000000000000000000000027fffffffffffffffffffff000000000000000000000000000000000000000000009094169588169590951792909217919091169290921795909517909455805193840181527f00000000000000000000000000000000000000000000000000000000000000008216845267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016928401929092527f00000000000000000000000000000000000000000000000000000000000000001682820152517f1406529d5e62f482fd1cd1a7e2ff03ff94c54a21619be336f55043d7c26fe83e91611dd09184906160ae565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a604051602001611e0099989796959493929190616162565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b8151600003611ec1576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611ad757611f28858281518110611ef657611ef6615c5a565b602002602001015184611f2257858381518110611f1557611f15615c5a565b6020026020010151612e39565b83612e39565b600101611ed8565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152611fbe82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642611fa29190615d71565b85608001516fffffffffffffffffffffffffffffffff166138b3565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b60005b815181101561248f57600082828151811061200257612002615c5a565b602002602001015190506000816000015190508067ffffffffffffffff16600003612065576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610773565b606082015173ffffffffffffffffffffffffffffffffffffffff166120b6576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600f60205260409020600181015473ffffffffffffffffffffffffffffffffffffffff16612333576040517fe9d68a8e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9d68a8e90602401606060405180830381865afa158015612185573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121a991906161f7565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff161415806121fb5750602081015167ffffffffffffffff1615155b1561223e576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610773565b61226d8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36138db565b600283015560608401516001830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92831617905560408086015184547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010091909316029190911783555167ffffffffffffffff841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1506123cb565b6060830151600182015473ffffffffffffffffffffffffffffffffffffffff9081169116141580612388575060408301518154610100900473ffffffffffffffffffffffffffffffffffffffff908116911614155b156123cb576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610773565b602083015181549015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617815560405167ffffffffffffffff8316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af079278490612479908490815460ff81161515825260081c73ffffffffffffffffffffffffffffffffffffffff90811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050611fe5565b5050565b6000610f1f8373ffffffffffffffffffffffffffffffffffffffff841661396a565b60006124d88473ffffffffffffffffffffffffffffffffffffffff851684613976565b90505b9392505050565b67ffffffffffffffff808316600090815260106020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915281205490918291168082036126045767ffffffffffffffff85166000908152600f6020526040902054610100900473ffffffffffffffffffffffffffffffffffffffff168015612602576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015282169063856c824790602401602060405180830381865afa1580156125d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125f5919061623f565b600193509350505061260b565b505b9150600090505b9250929050565b60006126208284018461625c565b60408051600080825260208201909252919250610dda918391612653565b606081526020019060019003908161263e5790505b50611e87565b815460009061268290700100000000000000000000000000000000900463ffffffff1642615d71565b9050801561272457600183015483546126ca916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166138b3565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461274a916fffffffffffffffffffffffffffffffff9081169116613999565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906128319084908151151581526020808301516fffffffffffffffffffffffffffffffff90811691830191909152604092830151169181019190915260600190565b60405180910390a1505050565b6000610f22826139af565b600080808061285886866139ba565b9097909650945050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036128e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610773565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b836000805b8651811015612d5557600085828151811061297c5761297c615c5a565b60200260200101518060200190518101906129979190616291565b905060006129a882602001516139c9565b90506129ea73ffffffffffffffffffffffffffffffffffffffff82167faff2afbf00000000000000000000000000000000000000000000000000000000612d6d565b612a38576040517fae9b4ce900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610773565b600080612ba4634059f55b60e01b6040518060e001604052808d6000015181526020018d6020015167ffffffffffffffff1681526020018d6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018e8981518110612aa157612aa1615c5a565b602002602001015160200151815260200187600001518152602001876040015181526020018b8981518110612ad857612ad8615c5a565b6020026020010151815250604051602401612af39190616346565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152600b54859063ffffffff7a010000000000000000000000000000000000000000000000000000909104166113886084613a24565b509150915081612be257806040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107739190614c71565b8051604014612c2c578051604080517f78ef802400000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604401610773565b60008082806020019051810190612c439190616420565b91509150612c5082613b4a565b898881518110612c6257612c62615c5a565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080898881518110612cb357612cb3615c5a565b60200260200101516020018181525050612cf4898881518110612cd857612cd8615c5a565b602002602001015160000151600c613be190919063ffffffff16565b15612d4457612d37898881518110612d0e57612d0e615c5a565b6020908102919091010151600b5473ffffffffffffffffffffffffffffffffffffffff16613c03565b612d419089615e18565b97505b50505050505080600101905061295f565b50801561138d5761138d81613d3e565b949350505050565b6000612d7883613d4b565b8015610f1f5750610f1f8383613daf565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff1681526020018460200151604051602001612e0e919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b81516040517f58babe3300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906358babe3390602401602060405180830381865afa158015612ecf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ef39190616444565b15612f36576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610773565b6020830151516000819003612f76576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360400151518114612fb4576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff82166000908152600f60205260409020805460ff16613014576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610773565b60008267ffffffffffffffff81111561302f5761302f614c84565b604051908082528060200260200182016040528015613058578160200160208202803683370190505b50905060005b8381101561311d5760008760200151828151811061307e5761307e615c5a565b60200260200101519050613096818560020154613e7e565b8383815181106130a8576130a8615c5a565b6020026020010181815250508061018001518383815181106130cc576130cc615c5a565b602002602001015114613114578061018001516040517f345039be00000000000000000000000000000000000000000000000000000000815260040161077391815260200190565b5060010161305e565b50606086015160808701516040517ffe41448f00000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263fe41448f9261319f928a928892600401616492565b602060405180830381865afa1580156131bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e091906164d9565b905080600003613228576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610773565b8551151560005b858110156138a85760008960200151828151811061324f5761324f615c5a565b602002602001015190506000613269898360600151610e94565b9050600281600381111561327f5761327f615679565b036132d55760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a150506138a0565b60008160038111156132e9576132e9615679565b14806133065750600381600381111561330457613304615679565b145b6133565760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610773565b831561341f57600a5460009063ffffffff166133728742615d71565b11905080806133925750600382600381111561339057613390615679565b145b6133d4576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b166004820152602401610773565b8a84815181106133e6576133e6615c5a565b6020026020010151600014613419578a848151811061340757613407615c5a565b60200260200101518360800181815250505b50613484565b600081600381111561343357613433615679565b146134845760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610773565b6000806134958b85602001516124e2565b9150915080156135b55760c084015167ffffffffffffffff166134b98360016164f2565b67ffffffffffffffff16146135495760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92613538928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60405180910390a1505050506138a0565b67ffffffffffffffff8b811660009081526010602090815260408083208883015173ffffffffffffffffffffffffffffffffffffffff168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169184169190911790555b60008360038111156135c9576135c9615679565b036136675760c084015167ffffffffffffffff166135e88360016164f2565b67ffffffffffffffff16146136675760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992613538928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60008d60400151868151811061367f5761367f615c5a565b602002602001015190506136ad8561018001518d876060015188610140015151896101200151518651614004565b6136bd8c86606001516001614154565b6000806136ca8784614232565b915091506136dd8e886060015184614154565b8880156136fb575060038260038111156136f9576136f9615679565b145b1561373b57866101800151816040517f2b11b8d9000000000000000000000000000000000000000000000000000000008152600401610773929190616513565b600382600381111561374f5761374f615679565b1415801561376f5750600282600381111561376c5761376c615679565b14155b156137b0578d8760600151836040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526004016107739392919061652c565b60008660038111156137c4576137c4615679565b0361383f5767ffffffffffffffff808f1660009081526010602090815260408083208b83015173ffffffffffffffffffffffffffffffffffffffff16845290915281208054909216919061381783616552565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df2858560405161389092919061656f565b60405180910390a4505050505050505b60010161322f565b505050505050505050565b60006138d2856138c38486615dda565b6138cd9087615e18565b613999565b95945050505050565b600081847f00000000000000000000000000000000000000000000000000000000000000008560405160200161394b949392919093845267ffffffffffffffff92831660208501529116604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b6040516020818303038152906040528051906020012090509392505050565b6000610f1f838361452c565b60006124d8848473ffffffffffffffffffffffffffffffffffffffff8516614549565b60008183106139a85781610f1f565b5090919050565b6000610f2282614566565b60008080806128588686614571565b60008151602014613a0857816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107739190614c71565b610f2282806020019051810190613a1f91906164d9565b613b4a565b6000606060008361ffff1667ffffffffffffffff811115613a4757613a47614c84565b6040519080825280601f01601f191660200182016040528015613a71576020820181803683370190505b509150863b613aa4577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ad7577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b10577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b335750835b808352806000602085013e50955095509592505050565b600073ffffffffffffffffffffffffffffffffffffffff821180613b6e5750600a82105b15613bdd57604080516020810184905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261077391600401614c71565b5090565b6000610f1f8373ffffffffffffffffffffffffffffffffffffffff841661459c565b81516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015260009182919084169063d02641a0906024016040805180830381865afa158015613c76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c9a919061658f565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116600003613d105783516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610773565b6020840151612d65907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316906145a8565b61119560038260006145e5565b6000613d77827f01ffc9a700000000000000000000000000000000000000000000000000000000613daf565b8015610f225750613da8827fffffffff00000000000000000000000000000000000000000000000000000000613daf565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015613e67575060208210155b8015613e735750600081115b979650505050505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b6101000151604051602001613f2198979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b6040516020818303038152906040528051906020012085610120015180519060200120866101400151604051602001613f5a91906165ef565b60405160208183030381529060405280519060200120876101600151604051602001613f86919061667a565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b600b5474010000000000000000000000000000000000000000900461ffff16831115614070576040517fa1e5205a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610773565b8083146140bd576040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610773565b600b54760100000000000000000000000000000000000000000000900463ffffffff1682111561414c57600b546040517f1fd8fd040000000000000000000000000000000000000000000000000000000081526004810188905276010000000000000000000000000000000000000000000090910463ffffffff16602482015260448101839052606401610773565b505050505050565b60006002614163608085615db3565b67ffffffffffffffff166141779190615dda565b67ffffffffffffffff8516600090815260116020526040812091925090816141a0608087615df1565b67ffffffffffffffff1681526020810191909152604001600020549050816141ca60016004615d71565b901b1916818360038111156141e1576141e1615679565b67ffffffffffffffff871660009081526011602052604081209190921b92909217918291614210608088615df1565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a590614276908790879060040161668d565b600060405180830381600087803b15801561429057600080fd5b505af19250505080156142a1575060015b614511573d8080156142cf576040519150601f19603f3d011682016040523d82523d6000602084013e6142d4565b606091505b506142de81616817565b7fffffffff00000000000000000000000000000000000000000000000000000000167f0a8d6e8c000000000000000000000000000000000000000000000000000000001480614376575061433181616817565b7fffffffff00000000000000000000000000000000000000000000000000000000167fe1cd550900000000000000000000000000000000000000000000000000000000145b806143ca575061438581616817565b7fffffffff00000000000000000000000000000000000000000000000000000000167f8d666f6000000000000000000000000000000000000000000000000000000000145b8061441e57506143d981616817565b7fffffffff00000000000000000000000000000000000000000000000000000000167f78ef802400000000000000000000000000000000000000000000000000000000145b80614472575061442d81616817565b7fffffffff00000000000000000000000000000000000000000000000000000000167f0c3b563c00000000000000000000000000000000000000000000000000000000145b806144c6575061448181616817565b7fffffffff00000000000000000000000000000000000000000000000000000000167fae9b4ce900000000000000000000000000000000000000000000000000000000145b156144d65760039250905061260b565b846101800151816040517f2b11b8d9000000000000000000000000000000000000000000000000000000008152600401610773929190616513565b50506040805160208101909152600081526002909250929050565b60008181526002830160205260408120819055610f1f8383614968565b600082815260028401602052604081208290556124d88484614974565b6000610f2282614980565b6000808061457f858561498a565b600081815260029690960160205260409095205494959350505050565b6000610f1f8383614996565b6000670de0b6b3a76400006145db837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615dda565b610f1f9190616867565b825474010000000000000000000000000000000000000000900460ff16158061460c575081155b1561461657505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061465c90700100000000000000000000000000000000900463ffffffff1642615d71565b9050801561471c578183111561469e576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546146d89083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166138b3565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156147d35773ffffffffffffffffffffffffffffffffffffffff841661477b576040517ff94ebcd10000000000000000000000000000000000000000000000000000000081526004810183905260248101869052604401610773565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff85166044820152606401610773565b848310156148e65760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906148179082615d71565b614821878a615d71565b61482b9190615e18565b6148359190616867565b905073ffffffffffffffffffffffffffffffffffffffff861661488e576040517f15279c080000000000000000000000000000000000000000000000000000000081526004810182905260248101869052604401610773565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff87166044820152606401610773565b6148f08584615d71565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b6000610f1f83836149b5565b6000610f1f8383614aaf565b6000610f22825490565b6000610f1f8383614afe565b6000610f1f838360008181526001830160205260408120541515610f1f565b60008181526001830160205260408120548015614a9e5760006149d9600183615d71565b85549091506000906149ed90600190615d71565b9050818114614a52576000866000018281548110614a0d57614a0d615c5a565b9060005260206000200154905080876000018481548110614a3057614a30615c5a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614a6357614a6361687b565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f22565b6000915050610f22565b5092915050565b6000818152600183016020526040812054614af657508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f22565b506000610f22565b6000826000018281548110614b1557614b15615c5a565b9060005260206000200154905092915050565b828054828255906000526020600020908101928215614ba2579160200282015b82811115614ba257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614b48565b50613bdd9291505b80821115613bdd5760008155600101614baa565b60608101610f228284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b60005b83811015614c1e578181015183820152602001614c06565b50506000910152565b60008151808452614c3f816020860160208601614c03565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610f1f6020830184614c27565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715614cd657614cd6614c84565b60405290565b6040516101a0810167ffffffffffffffff81118282101715614cd657614cd6614c84565b60405160a0810167ffffffffffffffff81118282101715614cd657614cd6614c84565b6040516080810167ffffffffffffffff81118282101715614cd657614cd6614c84565b6040516060810167ffffffffffffffff81118282101715614cd657614cd6614c84565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614db057614db0614c84565b604052919050565b600067ffffffffffffffff821115614dd257614dd2614c84565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff8116811461119557600080fd5b8035614e0981614ddc565b919050565b600082601f830112614e1f57600080fd5b81356020614e34614e2f83614db8565b614d69565b8083825260208201915060208460051b870101935086841115614e5657600080fd5b602086015b84811015614e7b578035614e6e81614ddc565b8352918301918301614e5b565b509695505050505050565b803560ff81168114614e0957600080fd5b600067ffffffffffffffff821115614eb157614eb1614c84565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112614eee57600080fd5b8135614efc614e2f82614e97565b818152846020838601011115614f1157600080fd5b816020850160208301376000918101602001919091529392505050565b67ffffffffffffffff8116811461119557600080fd5b8035614e0981614f2e565b60008060008060008060c08789031215614f6857600080fd5b863567ffffffffffffffff80821115614f8057600080fd5b614f8c8a838b01614e0e565b97506020890135915080821115614fa257600080fd5b614fae8a838b01614e0e565b9650614fbc60408a01614e86565b95506060890135915080821115614fd257600080fd5b614fde8a838b01614edd565b9450614fec60808a01614f44565b935060a089013591508082111561500257600080fd5b5061500f89828a01614edd565b9150509295509295509295565b801515811461119557600080fd5b8035614e098161501c565b600082601f83011261504657600080fd5b81356020615056614e2f83614db8565b82815260069290921b8401810191818101908684111561507557600080fd5b8286015b84811015614e7b57604081890312156150925760008081fd5b61509a614cb3565b81356150a581614ddc565b81528185013585820152835291830191604001615079565b600082601f8301126150ce57600080fd5b813560206150de614e2f83614db8565b82815260059290921b840181019181810190868411156150fd57600080fd5b8286015b84811015614e7b57803567ffffffffffffffff8111156151215760008081fd5b61512f8986838b0101614edd565b845250918301918301615101565b60006101a0828403121561515057600080fd5b615158614cdc565b905061516382614f44565b815261517160208301614dfe565b602082015261518260408301614dfe565b604082015261519360608301614f44565b6060820152608082013560808201526151ae60a0830161502a565b60a08201526151bf60c08301614f44565b60c08201526151d060e08301614dfe565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156151fd57600080fd5b61520986838701614edd565b8385015261014092508285013591508082111561522557600080fd5b61523186838701615035565b8385015261016092508285013591508082111561524d57600080fd5b5061525a858286016150bd565b82840152505061018080830135818301525092915050565b600082601f83011261528357600080fd5b81356020615293614e2f83614db8565b82815260059290921b840181019181810190868411156152b257600080fd5b8286015b84811015614e7b57803567ffffffffffffffff8111156152d65760008081fd5b6152e48986838b010161513d565b8452509183019183016152b6565b600082601f83011261530357600080fd5b81356020615313614e2f83614db8565b82815260059290921b8401810191818101908684111561533257600080fd5b8286015b84811015614e7b57803567ffffffffffffffff8111156153565760008081fd5b6153648986838b01016150bd565b845250918301918301615336565b600082601f83011261538357600080fd5b81356020615393614e2f83614db8565b8083825260208201915060208460051b8701019350868411156153b557600080fd5b602086015b84811015614e7b57803583529183019183016153ba565b600082601f8301126153e257600080fd5b813560206153f2614e2f83614db8565b82815260059290921b8401810191818101908684111561541157600080fd5b8286015b84811015614e7b57803567ffffffffffffffff808211156154365760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561546f5760008081fd5b615477614d00565b615482888501614f44565b8152604080850135848111156154985760008081fd5b6154a68e8b83890101615272565b8a84015250606080860135858111156154bf5760008081fd5b6154cd8f8c838a01016152f2565b83850152506080915081860135858111156154e85760008081fd5b6154f68f8c838a0101615372565b9184019190915250919093013590830152508352918301918301615415565b600080604080848603121561552957600080fd5b833567ffffffffffffffff8082111561554157600080fd5b61554d878388016153d1565b945060209150818601358181111561556457600080fd5b8601601f8101881361557557600080fd5b8035615583614e2f82614db8565b81815260059190911b8201840190848101908a8311156155a257600080fd5b8584015b8381101561562e578035868111156155be5760008081fd5b8501603f81018d136155d05760008081fd5b878101356155e0614e2f82614db8565b81815260059190911b82018a0190898101908f8311156156005760008081fd5b928b01925b8284101561561e5783358252928a0192908a0190615605565b86525050509186019186016155a6565b50809750505050505050509250929050565b6000806040838503121561565357600080fd5b823561565e81614f2e565b9150602083013561566e81614f2e565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106156df577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60208101610f2282846156a8565b60008151808452602080850194506020840160005b8381101561573857815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101615706565b509495945050505050565b602081526000610f1f60208301846156f1565b60006020828403121561576857600080fd5b81356124db81614ddc565b60c08101610f22828463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff8082166020860152806040850151166040860152505061ffff60608301511660608401528060808301511660808401528060a08301511660a0840152505050565b600060208083850312156157f557600080fd5b823567ffffffffffffffff81111561580c57600080fd5b8301601f8101851361581d57600080fd5b803561582b614e2f82614db8565b81815260079190911b8201830190838101908783111561584a57600080fd5b928401925b82841015613e7357608084890312156158685760008081fd5b615870614d23565b843561587b81614f2e565b81528486013561588a8161501c565b8187015260408581013561589d81614ddc565b908201526060858101356158b081614ddc565b908201528252608093909301929084019061584f565b6000602082840312156158d857600080fd5b813567ffffffffffffffff8111156158ef57600080fd5b820160a081850312156124db57600080fd5b600082601f83011261591257600080fd5b81356020615922614e2f83614db8565b82815260069290921b8401810191818101908684111561594157600080fd5b8286015b84811015614e7b576040818903121561595e5760008081fd5b615966614cb3565b813561597181614ddc565b81528185013561598081614ddc565b81860152835291830191604001615945565b600080604083850312156159a557600080fd5b823567ffffffffffffffff808211156159bd57600080fd5b6159c986838701615901565b935060208501359150808211156159df57600080fd5b506159ec85828601615901565b9150509250929050565b60008060408385031215615a0957600080fd5b8235615a1481614f2e565b9150602083013561566e81614ddc565b60008083601f840112615a3657600080fd5b50813567ffffffffffffffff811115615a4e57600080fd5b6020830191508360208260051b850101111561260b57600080fd5b60008060008060008060008060e0898b031215615a8557600080fd5b606089018a811115615a9657600080fd5b8998503567ffffffffffffffff80821115615ab057600080fd5b818b0191508b601f830112615ac457600080fd5b813581811115615ad357600080fd5b8c6020828501011115615ae557600080fd5b6020830199508098505060808b0135915080821115615b0357600080fd5b615b0f8c838d01615a24565b909750955060a08b0135915080821115615b2857600080fd5b50615b358b828c01615a24565b999c989b50969995989497949560c00135949350505050565b80356fffffffffffffffffffffffffffffffff81168114614e0957600080fd5b600060608284031215615b8057600080fd5b615b88614d46565b8235615b938161501c565b8152615ba160208401615b4e565b6020820152615bb260408401615b4e565b60408201529392505050565b600060208284031215615bd057600080fd5b81356124db81614f2e565b604081526000615bee60408301856156f1565b82810360208401526138d281856156f1565b60008060408385031215615c1357600080fd5b823567ffffffffffffffff80821115615c2b57600080fd5b615c378683870161513d565b93506020850135915080821115615c4d57600080fd5b506159ec858286016150bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103615cd157615cd1615c89565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152615d0b8184018a6156f1565b90508281036080840152615d1f81896156f1565b905060ff871660a084015282810360c0840152615d3c8187614c27565b905067ffffffffffffffff851660e0840152828103610100840152615d618185614c27565b9c9b505050505050505050505050565b81810381811115610f2257610f22615c89565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680615dce57615dce615d84565b92169190910692915050565b8082028115828204841417610f2257610f22615c89565b600067ffffffffffffffff80841680615e0c57615e0c615d84565b92169190910492915050565b80820180821115610f2257610f22615c89565b60008151808452602080850194506020840160005b83811015615738578151805173ffffffffffffffffffffffffffffffffffffffff1688528301518388015260409096019590820190600101615e40565b608081528451608082015267ffffffffffffffff60208601511660a08201526000604086015160a060c0840152615eb8610120840182614c27565b905060608701517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80808584030160e0860152615ef48383614c27565b925060808901519150808584030161010086015250615f138282615e2b565b92505050615f27602083018661ffff169052565b8360408301526138d2606083018473ffffffffffffffffffffffffffffffffffffffff169052565b600082601f830112615f6057600080fd5b8151615f6e614e2f82614e97565b818152846020838601011115615f8357600080fd5b612d65826020830160208701614c03565b600080600060608486031215615fa957600080fd5b8351615fb48161501c565b602085015190935067ffffffffffffffff811115615fd157600080fd5b615fdd86828701615f4f565b925050604084015190509250925092565b805163ffffffff81168114614e0957600080fd5b600060c0828403121561601457600080fd5b60405160c0810181811067ffffffffffffffff8211171561603757616037614c84565b60405261604383615fee565b8152602083015161605381614ddc565b6020820152604083015161606681614ddc565b6040820152606083015161ffff8116811461608057600080fd5b606082015261609160808401615fee565b60808201526160a260a08401615fee565b60a08201529392505050565b61012081016160f48285805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b6124db606083018463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff8082166020860152806040850151166040860152505061ffff60608301511660608401528060808301511660808401528060a08301511660a0840152505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526161a98285018b6156f1565b915083820360808501526161bd828a6156f1565b915060ff881660a085015283820360c08501526161da8288614c27565b90861660e08501528381036101008501529050615d618185614c27565b60006060828403121561620957600080fd5b616211614d46565b825161621c8161501c565b8152602083015161622c81614f2e565b60208201526040830151615bb281614ddc565b60006020828403121561625157600080fd5b81516124db81614f2e565b60006020828403121561626e57600080fd5b813567ffffffffffffffff81111561628557600080fd5b612d65848285016153d1565b6000602082840312156162a357600080fd5b815167ffffffffffffffff808211156162bb57600080fd5b90830190606082860312156162cf57600080fd5b6162d7614d46565b8251828111156162e657600080fd5b6162f287828601615f4f565b82525060208301518281111561630757600080fd5b61631387828601615f4f565b60208301525060408301518281111561632b57600080fd5b61633787828601615f4f565b60408301525095945050505050565b602081526000825160e06020840152616363610100840182614c27565b905067ffffffffffffffff602085015116604084015260408401516163a0606085018273ffffffffffffffffffffffffffffffffffffffff169052565b506060840151608084015260808401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160a08601526163e58383614c27565b925060a08601519150808584030160c08601526164028383614c27565b925060c08601519150808584030160e0860152506138d28282614c27565b6000806040838503121561643357600080fd5b505080516020909101519092909150565b60006020828403121561645657600080fd5b81516124db8161501c565b60008151808452602080850194506020840160005b8381101561573857815187529582019590820190600101616476565b67ffffffffffffffff851681526080602082015260006164b56080830186616461565b82810360408401526164c78186616461565b91505082606083015295945050505050565b6000602082840312156164eb57600080fd5b5051919050565b67ffffffffffffffff818116838216019080821115614aa857614aa8615c89565b8281526040602082015260006124d86040830184614c27565b67ffffffffffffffff84811682528316602082015260608101612d6560408301846156a8565b600067ffffffffffffffff808316818103615cd157615cd1615c89565b61657981846156a8565b6040602082015260006124d86040830184614c27565b6000604082840312156165a157600080fd5b6165a9614cb3565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146165d557600080fd5b81526165e360208401615fee565b60208201529392505050565b602081526000610f1f6020830184615e2b565b60008282518085526020808601955060208260051b8401016020860160005b8481101561666d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261665b838351614c27565b98840198925090830190600101616621565b5090979650505050505050565b602081526000610f1f6020830184616602565b604081526166a860408201845167ffffffffffffffff169052565b600060208401516166d1606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604084015173ffffffffffffffffffffffffffffffffffffffff8116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c084015161010061673f8185018367ffffffffffffffff169052565b60e0860151915061012061676a8186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061014091508282860152808701519250506101a0610160818187015261679a6101e0870185614c27565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06101808188870301818901526167d98686615e2b565b9550828a015194508188870301848901526167f48686616602565b9550808a01516101c0890152505050505082810360208401526138d28185616602565b6000815160208301517fffffffff000000000000000000000000000000000000000000000000000000008082169350600483101561685f5780818460040360031b1b83161693505b505050919050565b60008261687657616876615d84565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"InvalidMessageId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"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\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedSenderWithPreviousRampMessageInflight\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"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\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setOCR2Config\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b5060405162005e3038038062005e30833981016040819052620000359162000678565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200012c565b5050466080525081516001600160a01b0316620000ef576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160a01b0390811660a05260208301516001600160401b031660c05260408301511660e0526200012481620001d7565b505062000850565b336001600160a01b03821603620001865760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156200053a576000828281518110620001fb57620001fb620007e3565b60200260200101519050600081600001519050806001600160401b0316600003620002455760405163c39a620560e01b81526001600160401b038216600482015260240162000083565b60608201516001600160a01b031662000271576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260096020526040902060018101546001600160a01b0316620004395760a0516040516374eb454760e11b81526001600160401b03841660048201526000916001600160a01b03169063e9d68a8e90602401606060405180830381865afa158015620002ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003159190620007f9565b905083606001516001600160a01b031681604001516001600160a01b03161415806200034d575060208101516001600160401b031615155b15620003785760405163c39a620560e01b81526001600160401b038416600482015260240162000083565b620003af8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36200053e60201b60201c565b600283015560608401516001830180546001600160a01b0319166001600160a01b039283161790556040808601518454610100600160a81b0319166101009190931602919091178355516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150620004a0565b606083015160018201546001600160a01b0390811691161415806200047557506040830151815461010090046001600160a01b03908116911614155b15620004a05760405163c39a620560e01b81526001600160401b038316600482015260240162000083565b6020830151815490151560ff199091161781556040516001600160401b038316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af07927849062000523908490815460ff81161515825260081c6001600160a01b0390811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050620001da565b5050565b60c05160408051602081018490526001600160401b0380871692820192909252911660608201526001600160a01b038316608082015260009060a0016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620005d457620005d462000599565b60405290565b604051608081016001600160401b0381118282101715620005d457620005d462000599565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a62000599565b604052919050565b80516001600160a01b03811681146200064a57600080fd5b919050565b80516001600160401b03811681146200064a57600080fd5b805180151581146200064a57600080fd5b6000808284036080808212156200068e57600080fd5b6060808312156200069e57600080fd5b620006a8620005af565b9250620006b58662000632565b83526020620006c68188016200064f565b818501526040620006da6040890162000632565b604086015260608801519496506001600160401b0380861115620006fd57600080fd5b858901955089601f8701126200071257600080fd5b85518181111562000727576200072762000599565b62000737848260051b01620005ff565b818152848101925060079190911b87018401908b8211156200075857600080fd5b968401965b81881015620007d15786888d031215620007775760008081fd5b62000781620005da565b6200078c896200064f565b81526200079b868a0162000667565b86820152620007ac858a0162000632565b85820152620007bd878a0162000632565b81880152835296860196918401916200075d565b80985050505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b6000606082840312156200080c57600080fd5b62000816620005af565b620008218362000667565b815262000831602084016200064f565b6020820152620008446040840162000632565b60408201529392505050565b60805160a05160c05160e051615560620008d0600039600081816101d4015281816117aa01526124e90152600081816101a4015281816117840152612f2f0152600081816101680152818161175601528181611aab01526127de015260008181610a5a01528181610aa601528181610eff0152610f4b01526155606000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806381ff7048116100b2578063afcb95d711610081578063e9d68a8e11610066578063e9d68a8e14610491578063f2fde38b14610583578063f52121a51461059657600080fd5b8063afcb95d71461045e578063b1dc65a41461047e57600080fd5b806381ff7048146103cc57806385572ffb146103fc5780638b3643341461040a5780638da5cb5b1461043657600080fd5b80635e36480c116101095780637437ff9f116100ee5780637437ff9f146102cd57806379ba5097146103b15780637f63b711146103b957600080fd5b80635e36480c14610298578063666cab8d146102b857600080fd5b806306285c691461013b578063181f5a77146102275780631ef3817414610270578063542625af14610285575b600080fd5b610211604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161021e9190613a7e565b60405180910390f35b6102636040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b60405161021e9190613b31565b61028361027e366004613e0f565b6105a9565b005b6102836102933660046143d5565b610a57565b6102ab6102a6366004614500565b610c7f565b60405161021e91906145a3565b6102c0610d13565b60405161021e9190614603565b6103a46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260075463ffffffff808216835264010000000080830473ffffffffffffffffffffffffffffffffffffffff90811660208601527801000000000000000000000000000000000000000000000000840461ffff16958501959095527a0100000000000000000000000000000000000000000000000000009092048116606084015260085490811660808401520490911660a082015290565b60405161021e9190614616565b610283610d82565b6102836103c7366004614685565b610e7f565b6004546002546040805163ffffffff8085168252640100000000909404909316602084015282015260600161021e565b610283610136366004614769565b61041d6104183660046147a4565b610e93565b60405167ffffffffffffffff909116815260200161021e565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161021e565b60408051600181526000602082018190529181019190915260600161021e565b61028361048c366004614817565b610ea9565b61053361049f3660046148fc565b6040805160808101825260008082526020820181905291810182905260608101919091525067ffffffffffffffff166000908152600960209081526040918290208251608081018452815460ff81161515825273ffffffffffffffffffffffffffffffffffffffff610100909104811693820193909352600182015490921692820192909252600290910154606082015290565b6040805182511515815260208084015173ffffffffffffffffffffffffffffffffffffffff908116918301919091528383015116918101919091526060918201519181019190915260800161021e565b610283610591366004614919565b61113a565b6102836105a4366004614936565b61114b565b84518460ff16601f82111561061f576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f6f206d616e79207472616e736d697474657273000000000000000000000060448201526064015b60405180910390fd5b80600003610689576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610616565b610691611542565b61069a856115c5565b60065460005b8181101561071e5760056000600683815481106106bf576106bf61499a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016106a0565b50875160005b818110156109145760008a82815181106107405761074061499a565b602002602001015190506000600281111561075d5761075d614539565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561079c5761079c614539565b14610803576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610616565b73ffffffffffffffffffffffffffffffffffffffff8116610850576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561090057610900614539565b021790555090505050806001019050610724565b5088516109289060069060208c01906139e8565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908b1617179055600480546109ae9146913091906000906109809063ffffffff166149f8565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168d8d8d8d8d8d611809565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168e8e8e8e8e8e604051610a4299989796959493929190614a1b565b60405180910390a15050505050505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610ae2576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff46166024820152604401610616565b815181518114610b1e576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610c6f576000848281518110610b3d57610b3d61499a565b60200260200101519050600081602001515190506000858481518110610b6557610b6561499a565b6020026020010151905080518214610ba9576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610c60576000828281518110610bc857610bc861499a565b6020026020010151905080600014158015610c03575084602001518281518110610bf457610bf461499a565b60200260200101516080015181105b15610c575784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810183905260448101829052606401610616565b50600101610bac565b50505050806001019050610b21565b50610c7a83836118b4565b505050565b6000610c8d60016004614ab1565b6002610c9a608085614af3565b67ffffffffffffffff16610cae9190614b1a565b67ffffffffffffffff85166000908152600b6020526040812090610cd3608087614b31565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c166003811115610d0a57610d0a614539565b90505b92915050565b60606006805480602002602001604051908101604052809291908181526020018280548015610d7857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d4d575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610616565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e87611542565b610e9081611964565b50565b600080610ea08484611e15565b50949350505050565b610eb38787611f45565b600254883590808214610efc576040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610616565b467f000000000000000000000000000000000000000000000000000000000000000014610f7d576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610616565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526005602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561100557611005614539565b600281111561101657611016614539565b905250905060028160200151600281111561103357611033614539565b14801561107a57506006816000015160ff16815481106110555761105561499a565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6110b0576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006110be856020614b1a565b6110c9886020614b1a565b6110d58b610144614b58565b6110df9190614b58565b6110e99190614b58565b905036811461112d576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610616565b5050505050505050505050565b611142611542565b610e9081611f8c565b333014611184576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201909252816111c1565b604080518082019091526000808252602082015281526020019060019003908161119a5790505b50610140840151519091501561127a576101408301516040805160608101909152602085015173ffffffffffffffffffffffffffffffffffffffff16608082015261127791908060a08101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252875167ffffffffffffffff1660208301528781015173ffffffffffffffffffffffffffffffffffffffff1691015261016086015185612081565b90505b6101208301515115801561129057506080830151155b806112b45750604083015173ffffffffffffffffffffffffffffffffffffffff163b155b80611301575060408301516112ff9073ffffffffffffffffffffffffffffffffffffffff167f85572ffb000000000000000000000000000000000000000000000000000000006123e3565b155b1561130b57505050565b600061131784836123ff565b600854909150640100000000900473ffffffffffffffffffffffffffffffffffffffff168015611426576040517f9e6bd42300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690639e6bd42390611393908590600401614c2c565b600060405180830381600087803b1580156113ad57600080fd5b505af19250505080156113be575060015b611426573d8080156113ec576040519150601f19603f3d011682016040523d82523d6000602084013e6113f1565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b600754608086015160408088015190517f3cf97983000000000000000000000000000000000000000000000000000000008152600093849364010000000090910473ffffffffffffffffffffffffffffffffffffffff1692633cf979839261149692899261138892600401614c3f565b6000604051808303816000875af11580156114b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114fb9190810190614ccd565b50915091508161153957806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610616565b565b6000818060200190518101906115db9190614d3b565b602081015190915073ffffffffffffffffffffffffffffffffffffffff1661162f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516007805460208085015160408087015160608089015163ffffffff9081167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff61ffff909416780100000000000000000000000000000000000000000000000002939093167fffff000000000000ffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff9687166401000000009081027fffffffffffffffff0000000000000000000000000000000000000000000000009a8b169c85169c909c179b909b1716179290921790965560808801516008805460a08b015186169099029890961691161795909517909255835192830184527f00000000000000000000000000000000000000000000000000000000000000008216835267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016908301527f0000000000000000000000000000000000000000000000000000000000000000168183015290517f1c86233479b9d798a31091d42b1a954067dcd6c898553d63bf993757d2a90aff916117fd918490614de7565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a60405160200161182d99989796959493929190614e9b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b81516000036118ee576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561195d576119558582815181106119235761192361499a565b60200260200101518461194f578583815181106119425761194261499a565b60200260200101516124af565b836124af565b600101611905565b5050505050565b60005b8151811015611e115760008282815181106119845761198461499a565b602002602001015190506000816000015190508067ffffffffffffffff166000036119e7576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b606082015173ffffffffffffffffffffffffffffffffffffffff16611a38576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600960205260409020600181015473ffffffffffffffffffffffffffffffffffffffff16611cb5576040517fe9d68a8e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9d68a8e90602401606060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190614f30565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16141580611b7d5750602081015167ffffffffffffffff1615155b15611bc0576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b611bef8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3612f29565b600283015560608401516001830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92831617905560408086015184547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010091909316029190911783555167ffffffffffffffff841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150611d4d565b6060830151600182015473ffffffffffffffffffffffffffffffffffffffff9081169116141580611d0a575060408301518154610100900473ffffffffffffffffffffffffffffffffffffffff908116911614155b15611d4d576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610616565b602083015181549015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617815560405167ffffffffffffffff8316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af079278490611dfb908490815460ff81161515825260081c73ffffffffffffffffffffffffffffffffffffffff90811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050611967565b5050565b67ffffffffffffffff8083166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091829116808203611f375767ffffffffffffffff8516600090815260096020526040902054610100900473ffffffffffffffffffffffffffffffffffffffff168015611f35576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015282169063856c824790602401602060405180830381865afa158015611f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f289190614f84565b6001935093505050611f3e565b505b9150600090505b9250929050565b6000611f5382840184614fa1565b60408051600080825260208201909252919250610c7a918391611f86565b6060815260200190600190039081611f715790505b506118b4565b3373ffffffffffffffffffffffffffffffffffffffff82160361200b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610616565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8360005b8551811015610ea05760008482815181106120a2576120a261499a565b60200260200101518060200190518101906120bd9190614fd6565b905060006120ce8260200151612fb9565b905061211073ffffffffffffffffffffffffffffffffffffffff82167faff2afbf000000000000000000000000000000000000000000000000000000006123e3565b61215e576040517fae9b4ce900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610616565b6000806122ab634059f55b60e01b6040518060e001604052808c6000015181526020018c6020015167ffffffffffffffff1681526020018c6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018d89815181106121c7576121c761499a565b602002602001015160200151815260200187600001518152602001876040015181526020018a89815181106121fe576121fe61499a565b6020026020010151815250604051602401612219919061508b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152600854859063ffffffff166113886084613014565b5091509150816122e957806040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b8051604014612333578051604080517f78ef802400000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604401610616565b6000808280602001905181019061234a9190615165565b915091506123578261313a565b8888815181106123695761236961499a565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808888815181106123ba576123ba61499a565b60200260200101516020018181525050505050505050806001019050612085565b949350505050565b60006123ee836131d1565b8015610d0a5750610d0a8383613235565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff1681526020018460200151604051602001612484919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b81516040517f58babe3300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906358babe3390602401602060405180830381865afa158015612545573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125699190615189565b156125ac576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b60208301515160008190036125ec576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836040015151811461262a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff82166000908152600960205260409020805460ff1661268a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b60008267ffffffffffffffff8111156126a5576126a5613b44565b6040519080825280602002602001820160405280156126ce578160200160208202803683370190505b50905060005b83811015612793576000876020015182815181106126f4576126f461499a565b6020026020010151905061270c818560020154613304565b83838151811061271e5761271e61499a565b6020026020010181815250508061018001518383815181106127425761274261499a565b60200260200101511461278a578061018001516040517f345039be00000000000000000000000000000000000000000000000000000000815260040161061691815260200190565b506001016126d4565b50606086015160808701516040517ffe41448f00000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263fe41448f92612815928a9288926004016151d7565b602060405180830381865afa158015612832573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612856919061521e565b90508060000361289e576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610616565b8551151560005b85811015612f1e576000896020015182815181106128c5576128c561499a565b6020026020010151905060006128df898360600151610c7f565b905060028160038111156128f5576128f5614539565b0361294b5760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612f16565b600081600381111561295f5761295f614539565b148061297c5750600381600381111561297a5761297a614539565b145b6129cc5760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b8315612a955760075460009063ffffffff166129e88742614ab1565b1190508080612a0857506003826003811115612a0657612a06614539565b145b612a4a576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b166004820152602401610616565b8a8481518110612a5c57612a5c61499a565b6020026020010151600014612a8f578a8481518110612a7d57612a7d61499a565b60200260200101518360800181815250505b50612afa565b6000816003811115612aa957612aa9614539565b14612afa5760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b600080612b0b8b8560200151611e15565b915091508015612c2b5760c084015167ffffffffffffffff16612b2f836001615237565b67ffffffffffffffff1614612bbf5760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60405180910390a150505050612f16565b67ffffffffffffffff8b81166000908152600a602090815260408083208883015173ffffffffffffffffffffffffffffffffffffffff168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169184169190911790555b6000836003811115612c3f57612c3f614539565b03612cdd5760c084015167ffffffffffffffff16612c5e836001615237565b67ffffffffffffffff1614612cdd5760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60008d604001518681518110612cf557612cf561499a565b60200260200101519050612d238561018001518d87606001518861014001515189610120015151865161348a565b612d338c866060015160016135e6565b600080612d4087846136c4565b91509150612d538e8860600151846135e6565b888015612d7157506003826003811115612d6f57612d6f614539565b145b15612db157866101800151816040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b6003826003811115612dc557612dc5614539565b14158015612de557506002826003811115612de257612de2614539565b14155b15612e26578d8760600151836040517f926c5a3e00000000000000000000000000000000000000000000000000000000815260040161061693929190615278565b6000866003811115612e3a57612e3a614539565b03612eb55767ffffffffffffffff808f166000908152600a602090815260408083208b83015173ffffffffffffffffffffffffffffffffffffffff168452909152812080549092169190612e8d8361529e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051612f069291906152bb565b60405180910390a4505050505050505b6001016128a5565b505050505050505050565b600081847f000000000000000000000000000000000000000000000000000000000000000085604051602001612f99949392919093845267ffffffffffffffff92831660208501529116604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b60008151602014612ff857816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b610d0d8280602001905181019061300f919061521e565b61313a565b6000606060008361ffff1667ffffffffffffffff81111561303757613037613b44565b6040519080825280601f01601f191660200182016040528015613061576020820181803683370190505b509150863b613094577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a858110156130c7577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613100577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156131235750835b808352806000602085013e50955095509592505050565b600073ffffffffffffffffffffffffffffffffffffffff82118061315e5750600a82105b156131cd57604080516020810184905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261061691600401613b31565b5090565b60006131fd827f01ffc9a700000000000000000000000000000000000000000000000000000000613235565b8015610d0d575061322e827fffffffff00000000000000000000000000000000000000000000000000000000613235565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132ed575060208210155b80156132f95750600081115b979650505050505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016133a798979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016133e091906152db565b6040516020818303038152906040528051906020012087610160015160405160200161340c9190615366565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b6007547801000000000000000000000000000000000000000000000000900461ffff168311156134fa576040517fa1e5205a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b808314613547576040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b6007547a010000000000000000000000000000000000000000000000000000900463ffffffff168211156135de576007546040517f1fd8fd04000000000000000000000000000000000000000000000000000000008152600481018890527a01000000000000000000000000000000000000000000000000000090910463ffffffff16602482015260448101839052606401610616565b505050505050565b600060026135f5608085614af3565b67ffffffffffffffff166136099190614b1a565b67ffffffffffffffff85166000908152600b602052604081209192509081613632608087614b31565b67ffffffffffffffff16815260208101919091526040016000205490508161365c60016004614ab1565b901b19168183600381111561367357613673614539565b67ffffffffffffffff87166000908152600b602052604081209190921b929092179182916136a2608088614b31565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a5906137089087908790600401615379565b600060405180830381600087803b15801561372257600080fd5b505af1925050508015613733575060015b6139cd573d808015613761576040519150601f19603f3d011682016040523d82523d6000602084013e613766565b606091505b50600061377282615503565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216148061380557507fe1cd5509000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061385157507f8d666f60000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061389d57507f78ef8024000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b806138e957507f0c3b563c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061393557507fae9b4ce9000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061398157507f09c25325000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b156139925750600392509050611f3e565b856101800151826040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b50506040805160208101909152600081526002909250929050565b828054828255906000526020600020908101928215613a62579160200282015b82811115613a6257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613a08565b506131cd9291505b808211156131cd5760008155600101613a6a565b60608101610d0d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b60005b83811015613ade578181015183820152602001613ac6565b50506000910152565b60008151808452613aff816020860160208601613ac3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d0a6020830184613ae7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405290565b6040516101a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405160a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516080810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516060810167ffffffffffffffff81118282101715613b9657613b96613b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c7057613c70613b44565b604052919050565b600067ffffffffffffffff821115613c9257613c92613b44565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114610e9057600080fd5b8035613cc981613c9c565b919050565b600082601f830112613cdf57600080fd5b81356020613cf4613cef83613c78565b613c29565b8083825260208201915060208460051b870101935086841115613d1657600080fd5b602086015b84811015613d3b578035613d2e81613c9c565b8352918301918301613d1b565b509695505050505050565b803560ff81168114613cc957600080fd5b600067ffffffffffffffff821115613d7157613d71613b44565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613dae57600080fd5b8135613dbc613cef82613d57565b818152846020838601011115613dd157600080fd5b816020850160208301376000918101602001919091529392505050565b67ffffffffffffffff81168114610e9057600080fd5b8035613cc981613dee565b60008060008060008060c08789031215613e2857600080fd5b863567ffffffffffffffff80821115613e4057600080fd5b613e4c8a838b01613cce565b97506020890135915080821115613e6257600080fd5b613e6e8a838b01613cce565b9650613e7c60408a01613d46565b95506060890135915080821115613e9257600080fd5b613e9e8a838b01613d9d565b9450613eac60808a01613e04565b935060a0890135915080821115613ec257600080fd5b50613ecf89828a01613d9d565b9150509295509295509295565b8015158114610e9057600080fd5b8035613cc981613edc565b600082601f830112613f0657600080fd5b81356020613f16613cef83613c78565b82815260069290921b84018101918181019086841115613f3557600080fd5b8286015b84811015613d3b5760408189031215613f525760008081fd5b613f5a613b73565b8135613f6581613c9c565b81528185013585820152835291830191604001613f39565b600082601f830112613f8e57600080fd5b81356020613f9e613cef83613c78565b82815260059290921b84018101918181019086841115613fbd57600080fd5b8286015b84811015613d3b57803567ffffffffffffffff811115613fe15760008081fd5b613fef8986838b0101613d9d565b845250918301918301613fc1565b60006101a0828403121561401057600080fd5b614018613b9c565b905061402382613e04565b815261403160208301613cbe565b602082015261404260408301613cbe565b604082015261405360608301613e04565b60608201526080820135608082015261406e60a08301613eea565b60a082015261407f60c08301613e04565b60c082015261409060e08301613cbe565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156140bd57600080fd5b6140c986838701613d9d565b838501526101409250828501359150808211156140e557600080fd5b6140f186838701613ef5565b8385015261016092508285013591508082111561410d57600080fd5b5061411a85828601613f7d565b82840152505061018080830135818301525092915050565b600082601f83011261414357600080fd5b81356020614153613cef83613c78565b82815260059290921b8401810191818101908684111561417257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156141965760008081fd5b6141a48986838b0101613ffd565b845250918301918301614176565b600082601f8301126141c357600080fd5b813560206141d3613cef83613c78565b82815260059290921b840181019181810190868411156141f257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156142165760008081fd5b6142248986838b0101613f7d565b8452509183019183016141f6565b600082601f83011261424357600080fd5b81356020614253613cef83613c78565b8083825260208201915060208460051b87010193508684111561427557600080fd5b602086015b84811015613d3b578035835291830191830161427a565b600082601f8301126142a257600080fd5b813560206142b2613cef83613c78565b82815260059290921b840181019181810190868411156142d157600080fd5b8286015b84811015613d3b57803567ffffffffffffffff808211156142f65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561432f5760008081fd5b614337613bc0565b614342888501613e04565b8152604080850135848111156143585760008081fd5b6143668e8b83890101614132565b8a840152506060808601358581111561437f5760008081fd5b61438d8f8c838a01016141b2565b83850152506080915081860135858111156143a85760008081fd5b6143b68f8c838a0101614232565b91840191909152509190930135908301525083529183019183016142d5565b60008060408084860312156143e957600080fd5b833567ffffffffffffffff8082111561440157600080fd5b61440d87838801614291565b945060209150818601358181111561442457600080fd5b8601601f8101881361443557600080fd5b8035614443613cef82613c78565b81815260059190911b8201840190848101908a83111561446257600080fd5b8584015b838110156144ee5780358681111561447e5760008081fd5b8501603f81018d136144905760008081fd5b878101356144a0613cef82613c78565b81815260059190911b82018a0190898101908f8311156144c05760008081fd5b928b01925b828410156144de5783358252928a0192908a01906144c5565b8652505050918601918601614466565b50809750505050505050509250929050565b6000806040838503121561451357600080fd5b823561451e81613dee565b9150602083013561452e81613dee565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061459f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60208101610d0d8284614568565b60008151808452602080850194506020840160005b838110156145f857815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016145c6565b509495945050505050565b602081526000610d0a60208301846145b1565b60c08101610d0d828463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b6000602080838503121561469857600080fd5b823567ffffffffffffffff8111156146af57600080fd5b8301601f810185136146c057600080fd5b80356146ce613cef82613c78565b81815260079190911b820183019083810190878311156146ed57600080fd5b928401925b828410156132f9576080848903121561470b5760008081fd5b614713613be3565b843561471e81613dee565b81528486013561472d81613edc565b8187015260408581013561474081613c9c565b9082015260608581013561475381613c9c565b90820152825260809390930192908401906146f2565b60006020828403121561477b57600080fd5b813567ffffffffffffffff81111561479257600080fd5b820160a08185031215612fb257600080fd5b600080604083850312156147b757600080fd5b82356147c281613dee565b9150602083013561452e81613c9c565b60008083601f8401126147e457600080fd5b50813567ffffffffffffffff8111156147fc57600080fd5b6020830191508360208260051b8501011115611f3e57600080fd5b60008060008060008060008060e0898b03121561483357600080fd5b606089018a81111561484457600080fd5b8998503567ffffffffffffffff8082111561485e57600080fd5b818b0191508b601f83011261487257600080fd5b81358181111561488157600080fd5b8c602082850101111561489357600080fd5b6020830199508098505060808b01359150808211156148b157600080fd5b6148bd8c838d016147d2565b909750955060a08b01359150808211156148d657600080fd5b506148e38b828c016147d2565b999c989b50969995989497949560c00135949350505050565b60006020828403121561490e57600080fd5b8135612fb281613dee565b60006020828403121561492b57600080fd5b8135612fb281613c9c565b6000806040838503121561494957600080fd5b823567ffffffffffffffff8082111561496157600080fd5b61496d86838701613ffd565b9350602085013591508082111561498357600080fd5b5061499085828601613f7d565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103614a1157614a116149c9565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a4b8184018a6145b1565b90508281036080840152614a5f81896145b1565b905060ff871660a084015282810360c0840152614a7c8187613ae7565b905067ffffffffffffffff851660e0840152828103610100840152614aa18185613ae7565b9c9b505050505050505050505050565b81810381811115610d0d57610d0d6149c9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680614b0e57614b0e614ac4565b92169190910692915050565b8082028115828204841417610d0d57610d0d6149c9565b600067ffffffffffffffff80841680614b4c57614b4c614ac4565b92169190910492915050565b80820180821115610d0d57610d0d6149c9565b60008151808452602080850194506020840160005b838110156145f8578151805173ffffffffffffffffffffffffffffffffffffffff1688528301518388015260409096019590820190600101614b80565b8051825267ffffffffffffffff60208201511660208301526000604082015160a06040850152614bf060a0850182613ae7565b905060608301518482036060860152614c098282613ae7565b91505060808301518482036080860152614c238282614b6b565b95945050505050565b602081526000610d0a6020830184614bbd565b608081526000614c526080830187614bbd565b61ffff95909516602083015250604081019290925273ffffffffffffffffffffffffffffffffffffffff16606090910152919050565b600082601f830112614c9957600080fd5b8151614ca7613cef82613d57565b818152846020838601011115614cbc57600080fd5b6123db826020830160208701613ac3565b600080600060608486031215614ce257600080fd5b8351614ced81613edc565b602085015190935067ffffffffffffffff811115614d0a57600080fd5b614d1686828701614c88565b925050604084015190509250925092565b805163ffffffff81168114613cc957600080fd5b600060c08284031215614d4d57600080fd5b60405160c0810181811067ffffffffffffffff82111715614d7057614d70613b44565b604052614d7c83614d27565b81526020830151614d8c81613c9c565b6020820152604083015161ffff81168114614da657600080fd5b6040820152614db760608401614d27565b6060820152614dc860808401614d27565b608082015260a0830151614ddb81613c9c565b60a08201529392505050565b6101208101614e2d8285805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b612fb2606083018463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614ee28285018b6145b1565b91508382036080850152614ef6828a6145b1565b915060ff881660a085015283820360c0850152614f138288613ae7565b90861660e08501528381036101008501529050614aa18185613ae7565b600060608284031215614f4257600080fd5b614f4a613c06565b8251614f5581613edc565b81526020830151614f6581613dee565b60208201526040830151614f7881613c9c565b60408201529392505050565b600060208284031215614f9657600080fd5b8151612fb281613dee565b600060208284031215614fb357600080fd5b813567ffffffffffffffff811115614fca57600080fd5b6123db84828501614291565b600060208284031215614fe857600080fd5b815167ffffffffffffffff8082111561500057600080fd5b908301906060828603121561501457600080fd5b61501c613c06565b82518281111561502b57600080fd5b61503787828601614c88565b82525060208301518281111561504c57600080fd5b61505887828601614c88565b60208301525060408301518281111561507057600080fd5b61507c87828601614c88565b60408301525095945050505050565b602081526000825160e060208401526150a8610100840182613ae7565b905067ffffffffffffffff602085015116604084015260408401516150e5606085018273ffffffffffffffffffffffffffffffffffffffff169052565b506060840151608084015260808401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160a086015261512a8383613ae7565b925060a08601519150808584030160c08601526151478383613ae7565b925060c08601519150808584030160e086015250614c238282613ae7565b6000806040838503121561517857600080fd5b505080516020909101519092909150565b60006020828403121561519b57600080fd5b8151612fb281613edc565b60008151808452602080850194506020840160005b838110156145f8578151875295820195908201906001016151bb565b67ffffffffffffffff851681526080602082015260006151fa60808301866151a6565b828103604084015261520c81866151a6565b91505082606083015295945050505050565b60006020828403121561523057600080fd5b5051919050565b67ffffffffffffffff818116838216019080821115615258576152586149c9565b5092915050565b8281526040602082015260006123db6040830184613ae7565b67ffffffffffffffff848116825283166020820152606081016123db6040830184614568565b600067ffffffffffffffff808316818103614a1157614a116149c9565b6152c58184614568565b6040602082015260006123db6040830184613ae7565b602081526000610d0a6020830184614b6b565b60008282518085526020808601955060208260051b8401016020860160005b84811015615359577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952615347838351613ae7565b9884019892509083019060010161530d565b5090979650505050505050565b602081526000610d0a60208301846152ee565b6040815261539460408201845167ffffffffffffffff169052565b600060208401516153bd606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604084015173ffffffffffffffffffffffffffffffffffffffff8116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c084015161010061542b8185018367ffffffffffffffff169052565b60e086015191506101206154568186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061014091508282860152808701519250506101a061016081818701526154866101e0870185613ae7565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06101808188870301818901526154c58686614b6b565b9550828a015194508188870301848901526154e086866152ee565b9550808a01516101c089015250505050508281036020840152614c2381856152ee565b6000815160208301517fffffffff000000000000000000000000000000000000000000000000000000008082169350600483101561554b5780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", } var EVM2EVMMultiOffRampABI = EVM2EVMMultiOffRampMetaData.ABI var EVM2EVMMultiOffRampBin = EVM2EVMMultiOffRampMetaData.Bin -func DeployEVM2EVMMultiOffRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMMultiOffRampStaticConfig, sourceChainConfigs []EVM2EVMMultiOffRampSourceChainConfigArgs, rateLimiterConfig RateLimiterConfig) (common.Address, *types.Transaction, *EVM2EVMMultiOffRamp, error) { +func DeployEVM2EVMMultiOffRamp(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig EVM2EVMMultiOffRampStaticConfig, sourceChainConfigs []EVM2EVMMultiOffRampSourceChainConfigArgs) (common.Address, *types.Transaction, *EVM2EVMMultiOffRamp, error) { parsed, err := EVM2EVMMultiOffRampMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -133,7 +114,7 @@ func DeployEVM2EVMMultiOffRamp(auth *bind.TransactOpts, backend bind.ContractBac return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EVM2EVMMultiOffRampBin), backend, staticConfig, sourceChainConfigs, rateLimiterConfig) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EVM2EVMMultiOffRampBin), backend, staticConfig, sourceChainConfigs) if err != nil { return common.Address{}, nil, nil, err } @@ -276,58 +257,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) CcipReceive(arg0 C return _EVM2EVMMultiOffRamp.Contract.CcipReceive(&_EVM2EVMMultiOffRamp.CallOpts, arg0) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "currentRateLimiterState") - - if err != nil { - return *new(RateLimiterTokenBucket), err - } - - out0 := *abi.ConvertType(out[0], new(RateLimiterTokenBucket)).(*RateLimiterTokenBucket) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMMultiOffRamp.Contract.CurrentRateLimiterState(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) CurrentRateLimiterState() (RateLimiterTokenBucket, error) { - return _EVM2EVMMultiOffRamp.Contract.CurrentRateLimiterState(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetAllRateLimitTokens(opts *bind.CallOpts) (GetAllRateLimitTokens, - - error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getAllRateLimitTokens") - - outstruct := new(GetAllRateLimitTokens) - if err != nil { - return *outstruct, err - } - - outstruct.SourceTokens = *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - outstruct.DestTokens = *abi.ConvertType(out[1], new([]common.Address)).(*[]common.Address) - - return *outstruct, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetAllRateLimitTokens() (GetAllRateLimitTokens, - - error) { - return _EVM2EVMMultiOffRamp.Contract.GetAllRateLimitTokens(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetAllRateLimitTokens() (GetAllRateLimitTokens, - - error) { - return _EVM2EVMMultiOffRamp.Contract.GetAllRateLimitTokens(&_EVM2EVMMultiOffRamp.CallOpts) -} - func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOffRampDynamicConfig, error) { var out []interface{} err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getDynamicConfig") @@ -438,28 +367,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetStaticConfig() return _EVM2EVMMultiOffRamp.Contract.GetStaticConfig(&_EVM2EVMMultiOffRamp.CallOpts) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getTokenLimitAdmin") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMMultiOffRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMMultiOffRamp.CallOpts) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCallerSession) GetTokenLimitAdmin() (common.Address, error) { - return _EVM2EVMMultiOffRamp.Contract.GetTokenLimitAdmin(&_EVM2EVMMultiOffRamp.CallOpts) -} - func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampCaller) GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) { var out []interface{} err := _EVM2EVMMultiOffRamp.contract.Call(opts, &out, "getTransmitters") @@ -636,18 +543,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) ManuallyExecut return _EVM2EVMMultiOffRamp.Contract.ManuallyExecute(&_EVM2EVMMultiOffRamp.TransactOpts, reports, gasLimitOverrides) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "setAdmin", newAdmin) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetAdmin(&_EVM2EVMMultiOffRamp.TransactOpts, newAdmin) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetAdmin(newAdmin common.Address) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetAdmin(&_EVM2EVMMultiOffRamp.TransactOpts, newAdmin) -} - func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) { return _EVM2EVMMultiOffRamp.contract.Transact(opts, "setOCR2Config", signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) } @@ -660,18 +555,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetOCR2Config( return _EVM2EVMMultiOffRamp.Contract.SetOCR2Config(&_EVM2EVMMultiOffRamp.TransactOpts, signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "setRateLimiterConfig", config) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetRateLimiterConfig(&_EVM2EVMMultiOffRamp.TransactOpts, config) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) SetRateLimiterConfig(config RateLimiterConfig) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.SetRateLimiterConfig(&_EVM2EVMMultiOffRamp.TransactOpts, config) -} - func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _EVM2EVMMultiOffRamp.contract.Transact(opts, "transferOwnership", to) } @@ -696,20 +579,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) Transmit(repor return _EVM2EVMMultiOffRamp.Contract.Transmit(&_EVM2EVMMultiOffRamp.TransactOpts, reportContext, report, rs, ss, arg4) } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactor) UpdateRateLimitTokens(opts *bind.TransactOpts, removes []EVM2EVMMultiOffRampRateLimitToken, adds []EVM2EVMMultiOffRampRateLimitToken) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.contract.Transact(opts, "updateRateLimitTokens", removes, adds) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampSession) UpdateRateLimitTokens(removes []EVM2EVMMultiOffRampRateLimitToken, adds []EVM2EVMMultiOffRampRateLimitToken) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.UpdateRateLimitTokens(&_EVM2EVMMultiOffRamp.TransactOpts, removes, adds) -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampTransactorSession) UpdateRateLimitTokens(removes []EVM2EVMMultiOffRampRateLimitToken, adds []EVM2EVMMultiOffRampRateLimitToken) (*types.Transaction, error) { - return _EVM2EVMMultiOffRamp.Contract.UpdateRateLimitTokens(&_EVM2EVMMultiOffRamp.TransactOpts, removes, adds) -} - -type EVM2EVMMultiOffRampAdminSetIterator struct { - Event *EVM2EVMMultiOffRampAdminSet +type EVM2EVMMultiOffRampConfigSetIterator struct { + Event *EVM2EVMMultiOffRampConfigSet contract *bind.BoundContract event string @@ -720,7 +591,7 @@ type EVM2EVMMultiOffRampAdminSetIterator struct { fail error } -func (it *EVM2EVMMultiOffRampAdminSetIterator) Next() bool { +func (it *EVM2EVMMultiOffRampConfigSetIterator) Next() bool { if it.fail != nil { return false @@ -729,7 +600,7 @@ func (it *EVM2EVMMultiOffRampAdminSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampAdminSet) + it.Event = new(EVM2EVMMultiOffRampConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -744,7 +615,7 @@ func (it *EVM2EVMMultiOffRampAdminSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampAdminSet) + it.Event = new(EVM2EVMMultiOffRampConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -759,32 +630,33 @@ func (it *EVM2EVMMultiOffRampAdminSetIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampAdminSetIterator) Error() error { +func (it *EVM2EVMMultiOffRampConfigSetIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampAdminSetIterator) Close() error { +func (it *EVM2EVMMultiOffRampConfigSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampAdminSet struct { - NewAdmin common.Address - Raw types.Log +type EVM2EVMMultiOffRampConfigSet struct { + StaticConfig EVM2EVMMultiOffRampStaticConfig + DynamicConfig EVM2EVMMultiOffRampDynamicConfig + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampAdminSetIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSetIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "AdminSet") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ConfigSet") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampAdminSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "AdminSet", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampAdminSet) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "AdminSet") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ConfigSet") if err != nil { return nil, err } @@ -794,8 +666,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchAdminSet(opts *bin select { case log := <-logs: - event := new(EVM2EVMMultiOffRampAdminSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "AdminSet", log); err != nil { + event := new(EVM2EVMMultiOffRampConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { return err } event.Raw = log @@ -816,17 +688,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchAdminSet(opts *bin }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseAdminSet(log types.Log) (*EVM2EVMMultiOffRampAdminSet, error) { - event := new(EVM2EVMMultiOffRampAdminSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "AdminSet", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigSet(log types.Log) (*EVM2EVMMultiOffRampConfigSet, error) { + event := new(EVM2EVMMultiOffRampConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampConfigChangedIterator struct { - Event *EVM2EVMMultiOffRampConfigChanged +type EVM2EVMMultiOffRampConfigSet0Iterator struct { + Event *EVM2EVMMultiOffRampConfigSet0 contract *bind.BoundContract event string @@ -837,7 +709,7 @@ type EVM2EVMMultiOffRampConfigChangedIterator struct { fail error } -func (it *EVM2EVMMultiOffRampConfigChangedIterator) Next() bool { +func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { if it.fail != nil { return false @@ -846,7 +718,7 @@ func (it *EVM2EVMMultiOffRampConfigChangedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigChanged) + it.Event = new(EVM2EVMMultiOffRampConfigSet0) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -861,7 +733,7 @@ func (it *EVM2EVMMultiOffRampConfigChangedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigChanged) + it.Event = new(EVM2EVMMultiOffRampConfigSet0) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -876,32 +748,40 @@ func (it *EVM2EVMMultiOffRampConfigChangedIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampConfigChangedIterator) Error() error { +func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampConfigChangedIterator) Close() error { +func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampConfigChanged struct { - Config RateLimiterConfig - Raw types.Log +type EVM2EVMMultiOffRampConfigSet0 struct { + PreviousConfigBlockNumber uint32 + ConfigDigest [32]byte + ConfigCount uint64 + Signers []common.Address + Transmitters []common.Address + F uint8 + OnchainConfig []byte + OffchainConfigVersion uint64 + OffchainConfig []byte + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterConfigChanged(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigChangedIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterConfigSet0(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSet0Iterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ConfigChanged") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ConfigSet0") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampConfigChangedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ConfigChanged", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampConfigSet0Iterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ConfigSet0", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigChanged) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet0) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ConfigChanged") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ConfigSet0") if err != nil { return nil, err } @@ -911,8 +791,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigChanged(opts select { case log := <-logs: - event := new(EVM2EVMMultiOffRampConfigChanged) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigChanged", log); err != nil { + event := new(EVM2EVMMultiOffRampConfigSet0) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet0", log); err != nil { return err } event.Raw = log @@ -933,17 +813,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigChanged(opts }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigChanged(log types.Log) (*EVM2EVMMultiOffRampConfigChanged, error) { - event := new(EVM2EVMMultiOffRampConfigChanged) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigChanged", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigSet0(log types.Log) (*EVM2EVMMultiOffRampConfigSet0, error) { + event := new(EVM2EVMMultiOffRampConfigSet0) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet0", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampConfigSetIterator struct { - Event *EVM2EVMMultiOffRampConfigSet +type EVM2EVMMultiOffRampExecutionStateChangedIterator struct { + Event *EVM2EVMMultiOffRampExecutionStateChanged contract *bind.BoundContract event string @@ -954,7 +834,7 @@ type EVM2EVMMultiOffRampConfigSetIterator struct { fail error } -func (it *EVM2EVMMultiOffRampConfigSetIterator) Next() bool { +func (it *EVM2EVMMultiOffRampExecutionStateChangedIterator) Next() bool { if it.fail != nil { return false @@ -963,7 +843,7 @@ func (it *EVM2EVMMultiOffRampConfigSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigSet) + it.Event = new(EVM2EVMMultiOffRampExecutionStateChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -978,7 +858,7 @@ func (it *EVM2EVMMultiOffRampConfigSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigSet) + it.Event = new(EVM2EVMMultiOffRampExecutionStateChanged) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -993,33 +873,62 @@ func (it *EVM2EVMMultiOffRampConfigSetIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampConfigSetIterator) Error() error { +func (it *EVM2EVMMultiOffRampExecutionStateChangedIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampConfigSetIterator) Close() error { +func (it *EVM2EVMMultiOffRampExecutionStateChangedIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampConfigSet struct { - StaticConfig EVM2EVMMultiOffRampStaticConfig - DynamicConfig EVM2EVMMultiOffRampDynamicConfig - Raw types.Log +type EVM2EVMMultiOffRampExecutionStateChanged struct { + SourceChainSelector uint64 + SequenceNumber uint64 + MessageId [32]byte + State uint8 + ReturnData []byte + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSetIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*EVM2EVMMultiOffRampExecutionStateChangedIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ConfigSet") + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + var messageIdRule []interface{} + for _, messageIdItem := range messageId { + messageIdRule = append(messageIdRule, messageIdItem) + } + + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) if err != nil { return nil, err } - return &EVM2EVMMultiOffRampConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ConfigSet", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampExecutionStateChangedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ExecutionStateChanged", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ConfigSet") + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } + var sequenceNumberRule []interface{} + for _, sequenceNumberItem := range sequenceNumber { + sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) + } + var messageIdRule []interface{} + for _, messageIdItem := range messageId { + messageIdRule = append(messageIdRule, messageIdItem) + } + + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) if err != nil { return nil, err } @@ -1029,8 +938,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet(opts *bi select { case log := <-logs: - event := new(EVM2EVMMultiOffRampConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { + event := new(EVM2EVMMultiOffRampExecutionStateChanged) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { return err } event.Raw = log @@ -1051,17 +960,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet(opts *bi }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigSet(log types.Log) (*EVM2EVMMultiOffRampConfigSet, error) { - event := new(EVM2EVMMultiOffRampConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseExecutionStateChanged(log types.Log) (*EVM2EVMMultiOffRampExecutionStateChanged, error) { + event := new(EVM2EVMMultiOffRampExecutionStateChanged) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampConfigSet0Iterator struct { - Event *EVM2EVMMultiOffRampConfigSet0 +type EVM2EVMMultiOffRampOwnershipTransferRequestedIterator struct { + Event *EVM2EVMMultiOffRampOwnershipTransferRequested contract *bind.BoundContract event string @@ -1072,7 +981,7 @@ type EVM2EVMMultiOffRampConfigSet0Iterator struct { fail error } -func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { +func (it *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -1081,7 +990,7 @@ func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigSet0) + it.Event = new(EVM2EVMMultiOffRampOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1096,7 +1005,7 @@ func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampConfigSet0) + it.Event = new(EVM2EVMMultiOffRampOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1111,40 +1020,51 @@ func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Error() error { +func (it *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampConfigSet0Iterator) Close() error { +func (it *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampConfigSet0 struct { - PreviousConfigBlockNumber uint32 - ConfigDigest [32]byte - ConfigCount uint64 - Signers []common.Address - Transmitters []common.Address - F uint8 - OnchainConfig []byte - OffchainConfigVersion uint64 - OffchainConfig []byte - Raw types.Log +type EVM2EVMMultiOffRampOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterConfigSet0(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSet0Iterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferRequestedIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ConfigSet0") + 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 := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &EVM2EVMMultiOffRampConfigSet0Iterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ConfigSet0", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampOwnershipTransferRequestedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet0(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet0) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ConfigSet0") + 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 := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -1154,8 +1074,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet0(opts *b select { case log := <-logs: - event := new(EVM2EVMMultiOffRampConfigSet0) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet0", log); err != nil { + event := new(EVM2EVMMultiOffRampOwnershipTransferRequested) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -1176,673 +1096,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchConfigSet0(opts *b }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseConfigSet0(log types.Log) (*EVM2EVMMultiOffRampConfigSet0, error) { - event := new(EVM2EVMMultiOffRampConfigSet0) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ConfigSet0", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampExecutionStateChangedIterator struct { - Event *EVM2EVMMultiOffRampExecutionStateChanged - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampExecutionStateChangedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampExecutionStateChanged) - 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(EVM2EVMMultiOffRampExecutionStateChanged) - 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 *EVM2EVMMultiOffRampExecutionStateChangedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampExecutionStateChangedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampExecutionStateChanged struct { - SourceChainSelector uint64 - SequenceNumber uint64 - MessageId [32]byte - State uint8 - ReturnData []byte - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterExecutionStateChanged(opts *bind.FilterOpts, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (*EVM2EVMMultiOffRampExecutionStateChangedIterator, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } - var sequenceNumberRule []interface{} - for _, sequenceNumberItem := range sequenceNumber { - sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) - } - var messageIdRule []interface{} - for _, messageIdItem := range messageId { - messageIdRule = append(messageIdRule, messageIdItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampExecutionStateChangedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "ExecutionStateChanged", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchExecutionStateChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampExecutionStateChanged, sourceChainSelector []uint64, sequenceNumber []uint64, messageId [][32]byte) (event.Subscription, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } - var sequenceNumberRule []interface{} - for _, sequenceNumberItem := range sequenceNumber { - sequenceNumberRule = append(sequenceNumberRule, sequenceNumberItem) - } - var messageIdRule []interface{} - for _, messageIdItem := range messageId { - messageIdRule = append(messageIdRule, messageIdItem) - } - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "ExecutionStateChanged", sourceChainSelectorRule, sequenceNumberRule, messageIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampExecutionStateChanged) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseExecutionStateChanged(log types.Log) (*EVM2EVMMultiOffRampExecutionStateChanged, error) { - event := new(EVM2EVMMultiOffRampExecutionStateChanged) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "ExecutionStateChanged", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampOwnershipTransferRequestedIterator struct { - Event *EVM2EVMMultiOffRampOwnershipTransferRequested - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampOwnershipTransferRequested) - 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(EVM2EVMMultiOffRampOwnershipTransferRequested) - 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 *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferRequestedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferRequestedIterator, 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 := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampOwnershipTransferRequestedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferRequested, 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 := _EVM2EVMMultiOffRamp.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(EVM2EVMMultiOffRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOffRamp.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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferRequested, error) { - event := new(EVM2EVMMultiOffRampOwnershipTransferRequested) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampOwnershipTransferredIterator struct { - Event *EVM2EVMMultiOffRampOwnershipTransferred - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferredIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampOwnershipTransferred) - 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(EVM2EVMMultiOffRampOwnershipTransferred) - 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 *EVM2EVMMultiOffRampOwnershipTransferredIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampOwnershipTransferred struct { - From common.Address - To common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferredIterator, 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 := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampOwnershipTransferredIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferred, 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 := _EVM2EVMMultiOffRamp.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(EVM2EVMMultiOffRampOwnershipTransferred) - if err := _EVM2EVMMultiOffRamp.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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferred, error) { - event := new(EVM2EVMMultiOffRampOwnershipTransferred) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator struct { - Event *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - 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(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - 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 *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage struct { - SourceChainSelector uint64 - SequenceNumber uint64 - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSkippedAlreadyExecutedMessage(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SkippedAlreadyExecutedMessage") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SkippedAlreadyExecutedMessage", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedAlreadyExecutedMessage(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SkippedAlreadyExecutedMessage") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSkippedAlreadyExecutedMessage(log types.Log) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage, error) { - event := new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -type EVM2EVMMultiOffRampSkippedIncorrectNonceIterator struct { - Event *EVM2EVMMultiOffRampSkippedIncorrectNonce - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *EVM2EVMMultiOffRampSkippedIncorrectNonceIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSkippedIncorrectNonce) - 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(EVM2EVMMultiOffRampSkippedIncorrectNonce) - 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 *EVM2EVMMultiOffRampSkippedIncorrectNonceIterator) Error() error { - return it.fail -} - -func (it *EVM2EVMMultiOffRampSkippedIncorrectNonceIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type EVM2EVMMultiOffRampSkippedIncorrectNonce struct { - SourceChainSelector uint64 - Nonce uint64 - Sender common.Address - Raw types.Log -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSkippedIncorrectNonce(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedIncorrectNonceIterator, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SkippedIncorrectNonce") - if err != nil { - return nil, err - } - return &EVM2EVMMultiOffRampSkippedIncorrectNonceIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SkippedIncorrectNonce", logs: logs, sub: sub}, nil -} - -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedIncorrectNonce(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedIncorrectNonce) (event.Subscription, error) { - - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SkippedIncorrectNonce") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(EVM2EVMMultiOffRampSkippedIncorrectNonce) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedIncorrectNonce", 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 (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSkippedIncorrectNonce(log types.Log) (*EVM2EVMMultiOffRampSkippedIncorrectNonce, error) { - event := new(EVM2EVMMultiOffRampSkippedIncorrectNonce) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedIncorrectNonce", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseOwnershipTransferRequested(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferRequested, error) { + event := new(EVM2EVMMultiOffRampOwnershipTransferRequested) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator struct { - Event *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight +type EVM2EVMMultiOffRampOwnershipTransferredIterator struct { + Event *EVM2EVMMultiOffRampOwnershipTransferred contract *bind.BoundContract event string @@ -1853,7 +1117,7 @@ type EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator str fail error } -func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Next() bool { +func (it *EVM2EVMMultiOffRampOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -1862,7 +1126,7 @@ func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterato if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) + it.Event = new(EVM2EVMMultiOffRampOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1877,7 +1141,7 @@ func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterato select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) + it.Event = new(EVM2EVMMultiOffRampOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1892,34 +1156,51 @@ func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterato } } -func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Error() error { +func (it *EVM2EVMMultiOffRampOwnershipTransferredIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Close() error { +func (it *EVM2EVMMultiOffRampOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight struct { - SourceChainSelector uint64 - Nonce uint64 - Sender common.Address - Raw types.Log +type EVM2EVMMultiOffRampOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSkippedSenderWithPreviousRampMessageInflight(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*EVM2EVMMultiOffRampOwnershipTransferredIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SkippedSenderWithPreviousRampMessageInflight") + 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 := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SkippedSenderWithPreviousRampMessageInflight", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampOwnershipTransferredIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedSenderWithPreviousRampMessageInflight(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SkippedSenderWithPreviousRampMessageInflight") + 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 := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -1929,8 +1210,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedSenderWithP select { case log := <-logs: - event := new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedSenderWithPreviousRampMessageInflight", log); err != nil { + event := new(EVM2EVMMultiOffRampOwnershipTransferred) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -1951,17 +1232,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedSenderWithP }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSkippedSenderWithPreviousRampMessageInflight(log types.Log) (*EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight, error) { - event := new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedSenderWithPreviousRampMessageInflight", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseOwnershipTransferred(log types.Log) (*EVM2EVMMultiOffRampOwnershipTransferred, error) { + event := new(EVM2EVMMultiOffRampOwnershipTransferred) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampSourceChainConfigSetIterator struct { - Event *EVM2EVMMultiOffRampSourceChainConfigSet +type EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator struct { + Event *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage contract *bind.BoundContract event string @@ -1972,7 +1253,7 @@ type EVM2EVMMultiOffRampSourceChainConfigSetIterator struct { fail error } -func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Next() bool { +func (it *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Next() bool { if it.fail != nil { return false @@ -1981,7 +1262,7 @@ func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSourceChainConfigSet) + it.Event = new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1996,7 +1277,7 @@ func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSourceChainConfigSet) + it.Event = new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2011,43 +1292,33 @@ func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Error() error { +func (it *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Close() error { +func (it *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampSourceChainConfigSet struct { +type EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage struct { SourceChainSelector uint64 - SourceConfig EVM2EVMMultiOffRampSourceChainConfig + SequenceNumber uint64 Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSourceChainConfigSet(opts *bind.FilterOpts, sourceChainSelector []uint64) (*EVM2EVMMultiOffRampSourceChainConfigSetIterator, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSkippedAlreadyExecutedMessage(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SkippedAlreadyExecutedMessage") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampSourceChainConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SourceChainConfigSet", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampSkippedAlreadyExecutedMessageIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SkippedAlreadyExecutedMessage", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainConfigSet, sourceChainSelector []uint64) (event.Subscription, error) { - - var sourceChainSelectorRule []interface{} - for _, sourceChainSelectorItem := range sourceChainSelector { - sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) - } +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedAlreadyExecutedMessage(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SkippedAlreadyExecutedMessage") if err != nil { return nil, err } @@ -2057,8 +1328,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainConfigS select { case log := <-logs: - event := new(EVM2EVMMultiOffRampSourceChainConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainConfigSet", log); err != nil { + event := new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", log); err != nil { return err } event.Raw = log @@ -2079,17 +1350,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainConfigS }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSourceChainConfigSet(log types.Log) (*EVM2EVMMultiOffRampSourceChainConfigSet, error) { - event := new(EVM2EVMMultiOffRampSourceChainConfigSet) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainConfigSet", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSkippedAlreadyExecutedMessage(log types.Log) (*EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage, error) { + event := new(EVM2EVMMultiOffRampSkippedAlreadyExecutedMessage) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedAlreadyExecutedMessage", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampSourceChainSelectorAddedIterator struct { - Event *EVM2EVMMultiOffRampSourceChainSelectorAdded +type EVM2EVMMultiOffRampSkippedIncorrectNonceIterator struct { + Event *EVM2EVMMultiOffRampSkippedIncorrectNonce contract *bind.BoundContract event string @@ -2100,7 +1371,7 @@ type EVM2EVMMultiOffRampSourceChainSelectorAddedIterator struct { fail error } -func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Next() bool { +func (it *EVM2EVMMultiOffRampSkippedIncorrectNonceIterator) Next() bool { if it.fail != nil { return false @@ -2109,7 +1380,7 @@ func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSourceChainSelectorAdded) + it.Event = new(EVM2EVMMultiOffRampSkippedIncorrectNonce) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2124,7 +1395,7 @@ func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampSourceChainSelectorAdded) + it.Event = new(EVM2EVMMultiOffRampSkippedIncorrectNonce) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2139,32 +1410,34 @@ func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Error() error { +func (it *EVM2EVMMultiOffRampSkippedIncorrectNonceIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Close() error { +func (it *EVM2EVMMultiOffRampSkippedIncorrectNonceIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampSourceChainSelectorAdded struct { +type EVM2EVMMultiOffRampSkippedIncorrectNonce struct { SourceChainSelector uint64 + Nonce uint64 + Sender common.Address Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSourceChainSelectorAdded(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSourceChainSelectorAddedIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSkippedIncorrectNonce(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedIncorrectNonceIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SourceChainSelectorAdded") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SkippedIncorrectNonce") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampSourceChainSelectorAddedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SourceChainSelectorAdded", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampSkippedIncorrectNonceIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SkippedIncorrectNonce", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainSelectorAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainSelectorAdded) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedIncorrectNonce(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedIncorrectNonce) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SourceChainSelectorAdded") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SkippedIncorrectNonce") if err != nil { return nil, err } @@ -2174,8 +1447,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainSelecto select { case log := <-logs: - event := new(EVM2EVMMultiOffRampSourceChainSelectorAdded) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", log); err != nil { + event := new(EVM2EVMMultiOffRampSkippedIncorrectNonce) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedIncorrectNonce", log); err != nil { return err } event.Raw = log @@ -2196,17 +1469,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainSelecto }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSourceChainSelectorAdded(log types.Log) (*EVM2EVMMultiOffRampSourceChainSelectorAdded, error) { - event := new(EVM2EVMMultiOffRampSourceChainSelectorAdded) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSkippedIncorrectNonce(log types.Log) (*EVM2EVMMultiOffRampSkippedIncorrectNonce, error) { + event := new(EVM2EVMMultiOffRampSkippedIncorrectNonce) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedIncorrectNonce", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator struct { - Event *EVM2EVMMultiOffRampTokenAggregateRateLimitAdded +type EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator struct { + Event *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight contract *bind.BoundContract event string @@ -2217,7 +1490,7 @@ type EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator struct { fail error } -func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator) Next() bool { +func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Next() bool { if it.fail != nil { return false @@ -2226,7 +1499,7 @@ func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTokenAggregateRateLimitAdded) + it.Event = new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2241,7 +1514,7 @@ func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTokenAggregateRateLimitAdded) + it.Event = new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2256,33 +1529,34 @@ func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator) Error() error { +func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator) Close() error { +func (it *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampTokenAggregateRateLimitAdded struct { - SourceToken common.Address - DestToken common.Address - Raw types.Log +type EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight struct { + SourceChainSelector uint64 + Nonce uint64 + Sender common.Address + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterTokenAggregateRateLimitAdded(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSkippedSenderWithPreviousRampMessageInflight(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "TokenAggregateRateLimitAdded") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SkippedSenderWithPreviousRampMessageInflight") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "TokenAggregateRateLimitAdded", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflightIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SkippedSenderWithPreviousRampMessageInflight", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokenAggregateRateLimitAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTokenAggregateRateLimitAdded) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSkippedSenderWithPreviousRampMessageInflight(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "TokenAggregateRateLimitAdded") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SkippedSenderWithPreviousRampMessageInflight") if err != nil { return nil, err } @@ -2292,8 +1566,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokenAggregateRate select { case log := <-logs: - event := new(EVM2EVMMultiOffRampTokenAggregateRateLimitAdded) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "TokenAggregateRateLimitAdded", log); err != nil { + event := new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedSenderWithPreviousRampMessageInflight", log); err != nil { return err } event.Raw = log @@ -2314,17 +1588,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokenAggregateRate }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseTokenAggregateRateLimitAdded(log types.Log) (*EVM2EVMMultiOffRampTokenAggregateRateLimitAdded, error) { - event := new(EVM2EVMMultiOffRampTokenAggregateRateLimitAdded) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "TokenAggregateRateLimitAdded", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSkippedSenderWithPreviousRampMessageInflight(log types.Log) (*EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight, error) { + event := new(EVM2EVMMultiOffRampSkippedSenderWithPreviousRampMessageInflight) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SkippedSenderWithPreviousRampMessageInflight", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator struct { - Event *EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved +type EVM2EVMMultiOffRampSourceChainConfigSetIterator struct { + Event *EVM2EVMMultiOffRampSourceChainConfigSet contract *bind.BoundContract event string @@ -2335,7 +1609,7 @@ type EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator struct { fail error } -func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator) Next() bool { +func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Next() bool { if it.fail != nil { return false @@ -2344,7 +1618,7 @@ func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator) Next() bool if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved) + it.Event = new(EVM2EVMMultiOffRampSourceChainConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2359,7 +1633,7 @@ func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator) Next() bool select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved) + it.Event = new(EVM2EVMMultiOffRampSourceChainConfigSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2374,33 +1648,43 @@ func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator) Next() bool } } -func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator) Error() error { +func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator) Close() error { +func (it *EVM2EVMMultiOffRampSourceChainConfigSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved struct { - SourceToken common.Address - DestToken common.Address - Raw types.Log +type EVM2EVMMultiOffRampSourceChainConfigSet struct { + SourceChainSelector uint64 + SourceConfig EVM2EVMMultiOffRampSourceChainConfig + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterTokenAggregateRateLimitRemoved(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSourceChainConfigSet(opts *bind.FilterOpts, sourceChainSelector []uint64) (*EVM2EVMMultiOffRampSourceChainConfigSetIterator, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "TokenAggregateRateLimitRemoved") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) if err != nil { return nil, err } - return &EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "TokenAggregateRateLimitRemoved", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampSourceChainConfigSetIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SourceChainConfigSet", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokenAggregateRateLimitRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainConfigSet, sourceChainSelector []uint64) (event.Subscription, error) { + + var sourceChainSelectorRule []interface{} + for _, sourceChainSelectorItem := range sourceChainSelector { + sourceChainSelectorRule = append(sourceChainSelectorRule, sourceChainSelectorItem) + } - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "TokenAggregateRateLimitRemoved") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SourceChainConfigSet", sourceChainSelectorRule) if err != nil { return nil, err } @@ -2410,8 +1694,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokenAggregateRate select { case log := <-logs: - event := new(EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "TokenAggregateRateLimitRemoved", log); err != nil { + event := new(EVM2EVMMultiOffRampSourceChainConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainConfigSet", log); err != nil { return err } event.Raw = log @@ -2432,17 +1716,17 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokenAggregateRate }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseTokenAggregateRateLimitRemoved(log types.Log) (*EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved, error) { - event := new(EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "TokenAggregateRateLimitRemoved", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSourceChainConfigSet(log types.Log) (*EVM2EVMMultiOffRampSourceChainConfigSet, error) { + event := new(EVM2EVMMultiOffRampSourceChainConfigSet) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainConfigSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type EVM2EVMMultiOffRampTokensConsumedIterator struct { - Event *EVM2EVMMultiOffRampTokensConsumed +type EVM2EVMMultiOffRampSourceChainSelectorAddedIterator struct { + Event *EVM2EVMMultiOffRampSourceChainSelectorAdded contract *bind.BoundContract event string @@ -2453,7 +1737,7 @@ type EVM2EVMMultiOffRampTokensConsumedIterator struct { fail error } -func (it *EVM2EVMMultiOffRampTokensConsumedIterator) Next() bool { +func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Next() bool { if it.fail != nil { return false @@ -2462,7 +1746,7 @@ func (it *EVM2EVMMultiOffRampTokensConsumedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTokensConsumed) + it.Event = new(EVM2EVMMultiOffRampSourceChainSelectorAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2477,7 +1761,7 @@ func (it *EVM2EVMMultiOffRampTokensConsumedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(EVM2EVMMultiOffRampTokensConsumed) + it.Event = new(EVM2EVMMultiOffRampSourceChainSelectorAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2492,32 +1776,32 @@ func (it *EVM2EVMMultiOffRampTokensConsumedIterator) Next() bool { } } -func (it *EVM2EVMMultiOffRampTokensConsumedIterator) Error() error { +func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Error() error { return it.fail } -func (it *EVM2EVMMultiOffRampTokensConsumedIterator) Close() error { +func (it *EVM2EVMMultiOffRampSourceChainSelectorAddedIterator) Close() error { it.sub.Unsubscribe() return nil } -type EVM2EVMMultiOffRampTokensConsumed struct { - Tokens *big.Int - Raw types.Log +type EVM2EVMMultiOffRampSourceChainSelectorAdded struct { + SourceChainSelector uint64 + Raw types.Log } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterTokensConsumed(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampTokensConsumedIterator, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) FilterSourceChainSelectorAdded(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampSourceChainSelectorAddedIterator, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "TokensConsumed") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.FilterLogs(opts, "SourceChainSelectorAdded") if err != nil { return nil, err } - return &EVM2EVMMultiOffRampTokensConsumedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "TokensConsumed", logs: logs, sub: sub}, nil + return &EVM2EVMMultiOffRampSourceChainSelectorAddedIterator{contract: _EVM2EVMMultiOffRamp.contract, event: "SourceChainSelectorAdded", logs: logs, sub: sub}, nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTokensConsumed) (event.Subscription, error) { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchSourceChainSelectorAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampSourceChainSelectorAdded) (event.Subscription, error) { - logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "TokensConsumed") + logs, sub, err := _EVM2EVMMultiOffRamp.contract.WatchLogs(opts, "SourceChainSelectorAdded") if err != nil { return nil, err } @@ -2527,8 +1811,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokensConsumed(opt select { case log := <-logs: - event := new(EVM2EVMMultiOffRampTokensConsumed) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "TokensConsumed", log); err != nil { + event := new(EVM2EVMMultiOffRampSourceChainSelectorAdded) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", log); err != nil { return err } event.Raw = log @@ -2549,9 +1833,9 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) WatchTokensConsumed(opt }), nil } -func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseTokensConsumed(log types.Log) (*EVM2EVMMultiOffRampTokensConsumed, error) { - event := new(EVM2EVMMultiOffRampTokensConsumed) - if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "TokensConsumed", log); err != nil { +func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseSourceChainSelectorAdded(log types.Log) (*EVM2EVMMultiOffRampSourceChainSelectorAdded, error) { + event := new(EVM2EVMMultiOffRampSourceChainSelectorAdded) + if err := _EVM2EVMMultiOffRamp.contract.UnpackLog(event, "SourceChainSelectorAdded", log); err != nil { return nil, err } event.Raw = log @@ -2676,10 +1960,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRampFilterer) ParseTransmitted(log ty return event, nil } -type GetAllRateLimitTokens struct { - SourceTokens []common.Address - DestTokens []common.Address -} type LatestConfigDetails struct { ConfigCount uint32 BlockNumber uint32 @@ -2693,10 +1973,6 @@ type LatestConfigDigestAndEpoch struct { func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _EVM2EVMMultiOffRamp.abi.Events["AdminSet"].ID: - return _EVM2EVMMultiOffRamp.ParseAdminSet(log) - case _EVM2EVMMultiOffRamp.abi.Events["ConfigChanged"].ID: - return _EVM2EVMMultiOffRamp.ParseConfigChanged(log) case _EVM2EVMMultiOffRamp.abi.Events["ConfigSet"].ID: return _EVM2EVMMultiOffRamp.ParseConfigSet(log) case _EVM2EVMMultiOffRamp.abi.Events["ConfigSet0"].ID: @@ -2717,12 +1993,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) ParseLog(log types.Log) (genera return _EVM2EVMMultiOffRamp.ParseSourceChainConfigSet(log) case _EVM2EVMMultiOffRamp.abi.Events["SourceChainSelectorAdded"].ID: return _EVM2EVMMultiOffRamp.ParseSourceChainSelectorAdded(log) - case _EVM2EVMMultiOffRamp.abi.Events["TokenAggregateRateLimitAdded"].ID: - return _EVM2EVMMultiOffRamp.ParseTokenAggregateRateLimitAdded(log) - case _EVM2EVMMultiOffRamp.abi.Events["TokenAggregateRateLimitRemoved"].ID: - return _EVM2EVMMultiOffRamp.ParseTokenAggregateRateLimitRemoved(log) - case _EVM2EVMMultiOffRamp.abi.Events["TokensConsumed"].ID: - return _EVM2EVMMultiOffRamp.ParseTokensConsumed(log) case _EVM2EVMMultiOffRamp.abi.Events["Transmitted"].ID: return _EVM2EVMMultiOffRamp.ParseTransmitted(log) @@ -2731,16 +2001,8 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) ParseLog(log types.Log) (genera } } -func (EVM2EVMMultiOffRampAdminSet) Topic() common.Hash { - return common.HexToHash("0x8fe72c3e0020beb3234e76ae6676fa576fbfcae600af1c4fea44784cf0db329c") -} - -func (EVM2EVMMultiOffRampConfigChanged) Topic() common.Hash { - return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") -} - func (EVM2EVMMultiOffRampConfigSet) Topic() common.Hash { - return common.HexToHash("0x1406529d5e62f482fd1cd1a7e2ff03ff94c54a21619be336f55043d7c26fe83e") + return common.HexToHash("0x1c86233479b9d798a31091d42b1a954067dcd6c898553d63bf993757d2a90aff") } func (EVM2EVMMultiOffRampConfigSet0) Topic() common.Hash { @@ -2779,18 +2041,6 @@ func (EVM2EVMMultiOffRampSourceChainSelectorAdded) Topic() common.Hash { return common.HexToHash("0xf4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb9") } -func (EVM2EVMMultiOffRampTokenAggregateRateLimitAdded) Topic() common.Hash { - return common.HexToHash("0xfc23abf7ddbd3c02b1420dafa2355c56c1a06fbb8723862ac14d6bd74177361a") -} - -func (EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved) Topic() common.Hash { - return common.HexToHash("0xcbf3cbeaed4ac1d605ed30f4af06c35acaeff2379db7f6146c9cceee83d58782") -} - -func (EVM2EVMMultiOffRampTokensConsumed) Topic() common.Hash { - return common.HexToHash("0x1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a") -} - func (EVM2EVMMultiOffRampTransmitted) Topic() common.Hash { return common.HexToHash("0xb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62") } @@ -2802,12 +2052,6 @@ func (_EVM2EVMMultiOffRamp *EVM2EVMMultiOffRamp) Address() common.Address { type EVM2EVMMultiOffRampInterface interface { CcipReceive(opts *bind.CallOpts, arg0 ClientAny2EVMMessage) error - CurrentRateLimiterState(opts *bind.CallOpts) (RateLimiterTokenBucket, error) - - GetAllRateLimitTokens(opts *bind.CallOpts) (GetAllRateLimitTokens, - - error) - GetDynamicConfig(opts *bind.CallOpts) (EVM2EVMMultiOffRampDynamicConfig, error) GetExecutionState(opts *bind.CallOpts, sourceChainSelector uint64, sequenceNumber uint64) (uint8, error) @@ -2818,8 +2062,6 @@ type EVM2EVMMultiOffRampInterface interface { GetStaticConfig(opts *bind.CallOpts) (EVM2EVMMultiOffRampStaticConfig, error) - GetTokenLimitAdmin(opts *bind.CallOpts) (common.Address, error) - GetTransmitters(opts *bind.CallOpts) ([]common.Address, error) LatestConfigDetails(opts *bind.CallOpts) (LatestConfigDetails, @@ -2842,30 +2084,12 @@ type EVM2EVMMultiOffRampInterface interface { ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) - SetAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) - SetOCR2Config(opts *bind.TransactOpts, signers []common.Address, transmitters []common.Address, f uint8, onchainConfig []byte, offchainConfigVersion uint64, offchainConfig []byte) (*types.Transaction, error) - SetRateLimiterConfig(opts *bind.TransactOpts, config RateLimiterConfig) (*types.Transaction, error) - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) Transmit(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte, rs [][32]byte, ss [][32]byte, arg4 [32]byte) (*types.Transaction, error) - UpdateRateLimitTokens(opts *bind.TransactOpts, removes []EVM2EVMMultiOffRampRateLimitToken, adds []EVM2EVMMultiOffRampRateLimitToken) (*types.Transaction, error) - - FilterAdminSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampAdminSetIterator, error) - - WatchAdminSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampAdminSet) (event.Subscription, error) - - ParseAdminSet(log types.Log) (*EVM2EVMMultiOffRampAdminSet, error) - - FilterConfigChanged(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigChangedIterator, error) - - WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigChanged) (event.Subscription, error) - - ParseConfigChanged(log types.Log) (*EVM2EVMMultiOffRampConfigChanged, error) - FilterConfigSet(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampConfigSetIterator, error) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampConfigSet) (event.Subscription, error) @@ -2926,24 +2150,6 @@ type EVM2EVMMultiOffRampInterface interface { ParseSourceChainSelectorAdded(log types.Log) (*EVM2EVMMultiOffRampSourceChainSelectorAdded, error) - FilterTokenAggregateRateLimitAdded(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampTokenAggregateRateLimitAddedIterator, error) - - WatchTokenAggregateRateLimitAdded(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTokenAggregateRateLimitAdded) (event.Subscription, error) - - ParseTokenAggregateRateLimitAdded(log types.Log) (*EVM2EVMMultiOffRampTokenAggregateRateLimitAdded, error) - - FilterTokenAggregateRateLimitRemoved(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampTokenAggregateRateLimitRemovedIterator, error) - - WatchTokenAggregateRateLimitRemoved(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved) (event.Subscription, error) - - ParseTokenAggregateRateLimitRemoved(log types.Log) (*EVM2EVMMultiOffRampTokenAggregateRateLimitRemoved, error) - - FilterTokensConsumed(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampTokensConsumedIterator, error) - - WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTokensConsumed) (event.Subscription, error) - - ParseTokensConsumed(log types.Log) (*EVM2EVMMultiOffRampTokensConsumed, error) - FilterTransmitted(opts *bind.FilterOpts) (*EVM2EVMMultiOffRampTransmittedIterator, error) WatchTransmitted(opts *bind.WatchOpts, sink chan<- *EVM2EVMMultiOffRampTransmitted) (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 c7b7e0ba54..874c529e45 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 @@ -9,7 +9,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 bd56fec69d252bd9b87b5dd647e2eca937cf0b92674c824aa5f17427eba1c657 custom_token_pool: ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.abi ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.bin 488bd34d63be7b731f4fbdf0cd353f7e4fbee990cfa4db26be91973297d3f803 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin b398a1906f73f9ce537954611f995447ef1ac810532c6866cecf0bd19b9c357c -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 13b1aeccfd45e2725b9f90281034405b90f3b064621ca1d26267674c454e77a2 +evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin b21c98fa8a88195af432661f96318964b26359438caddfee98f1eee537bae9c4 evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin c4f9946b23a0887d8744e203a6d9a50252fc0ed949348bd52f2b810e14940081 evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin 0daedb073a1b3563eb014f3363e0c796ade734ffbb217562f47101fdf0837c4a evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin ccd73e2c7e07bac0805da8fa09bcd4434ddf69296e6cb75e4c6933276ffac129 From b67f9c2037b54076d3a0bf1220dfe2a5fc263495 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Thu, 23 May 2024 17:38:21 +0200 Subject: [PATCH 11/23] refactor: move multi-arl back to root contracts dir --- .../MultiAggregateRateLimiter.sol | 16 ++++++++-------- .../helpers/MultiAggregateRateLimiterHelper.sol | 2 +- .../rateLimiter/MultiAggregateRateLimiter.t.sol | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) rename contracts/src/v0.8/ccip/{validators => }/MultiAggregateRateLimiter.sol (96%) diff --git a/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol similarity index 96% rename from contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol rename to contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 04e4209fb0..54d8fa73cb 100644 --- a/contracts/src/v0.8/ccip/validators/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IMessageValidator} from "../interfaces/IMessageValidator.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; - -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {EnumerableMapAddresses} from "../../shared/enumerable/EnumerableMapAddresses.sol"; -import {Client} from "../libraries/Client.sol"; -import {RateLimiterNoEvents} from "../libraries/RateLimiterNoEvents.sol"; -import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.sol"; +import {IMessageValidator} from "./interfaces/IMessageValidator.sol"; +import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; + +import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; +import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; +import {Client} from "./libraries/Client.sol"; +import {RateLimiterNoEvents} from "./libraries/RateLimiterNoEvents.sol"; +import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index b055129ae8..b7808759b5 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; import {Client} from "../../libraries/Client.sol"; -import {MultiAggregateRateLimiter} from "../../validators/MultiAggregateRateLimiter.sol"; contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { constructor( diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 6f48a470f1..9b1c8c8c4b 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -3,10 +3,10 @@ pragma solidity 0.8.24; import {Vm} from "forge-std/Vm.sol"; +import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; -import {MultiAggregateRateLimiter} from "../../validators/MultiAggregateRateLimiter.sol"; import {BaseTest} from "../BaseTest.t.sol"; import {MultiAggregateRateLimiterHelper} from "../helpers/MultiAggregateRateLimiterHelper.sol"; import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; From b56c0e82684749404c4b51b0609c02c4f0f4a143 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Fri, 24 May 2024 10:51:13 +0200 Subject: [PATCH 12/23] perf: remove unnecessary variable caching and style changes --- contracts/gas-snapshots/ccip.gas-snapshot | 20 +++++++++---------- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 19 +++++++++--------- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 2 -- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index fcb92ffeba..e07de05251 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -462,19 +462,19 @@ MultiAggregateRateLimiter__getTokenValue:test_NoTokenPrice_Reverts() (gas: 21221 MultiAggregateRateLimiter__rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16940) MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValueDifferentChainSelectors_Success() (gas: 9223372036854754743) MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValue_Success_gas() (gas: 18930) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 188570) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 187973) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByAdminOrOwner_Revert() (gas: 19288) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigByAdmin_Success() (gas: 77318) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 74783) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 35690) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 37574) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigByAdmin_Success() (gas: 77119) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 74584) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 35314) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 37198) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 16890) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12353) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1949294) -MultiAggregateRateLimiter_constructor:test_ConstructorNoConfigs_Success() (gas: 1999748) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2118549) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1923613) +MultiAggregateRateLimiter_constructor:test_ConstructorNoConfigs_Success() (gas: 1974067) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2092466) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 20062) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 44944) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 44668) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15672) MultiAggregateRateLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10553) MultiAggregateRateLimiter_setAdmin:test_Admin_Success() (gas: 19485) @@ -501,7 +501,7 @@ MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (g MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14428) MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 64621) MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithNoTokens_Success() (gas: 15140) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 66380) +MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 66104) MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50047) MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 77710) MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 88029) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 54d8fa73cb..fafea88fa6 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -45,6 +45,12 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { address[] removedCallers; } + /// @notice Update args for a single rate limiter config update + struct RateLimiterConfigArgs { + uint64 chainSelector; // Chain selector to set config for + RateLimiterNoEvents.Config rateLimiterConfig; // Rate limiter config to set + } + /// @dev Tokens that should be included in Aggregate Rate Limiting (from dest -> source) EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensDestToSource; @@ -59,12 +65,6 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Rate limiter token bucket states per chain mapping(uint64 chainSelector => RateLimiterNoEvents.TokenBucket rateLimiter) s_rateLimitersByChainSelector; - /// @notice Update args for a single rate limiter config update - struct RateLimiterConfigArgs { - uint64 chainSelector; // Chain selector to set config for - RateLimiterNoEvents.Config rateLimiterConfig; // Rate limiter config to set - } - /// @param rateLimiterConfigs The RateLimiterNoEvents.Configs per chain containing the capacity and refill rate /// of the bucket /// @param admin the admin address to set @@ -150,10 +150,9 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { revert ZeroChainSelectorNotAllowed(); } - RateLimiterNoEvents.TokenBucket memory tokenBucket = s_rateLimitersByChainSelector[chainSelector]; - uint32 lastUpdated = tokenBucket.lastUpdated; + RateLimiterNoEvents.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[chainSelector]; - if (lastUpdated == 0) { + if (tokenBucket.lastUpdated == 0) { // Token bucket needs to be newly added s_rateLimitersByChainSelector[chainSelector] = RateLimiterNoEvents.TokenBucket({ rate: configUpdate.rate, @@ -163,7 +162,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { isEnabled: configUpdate.isEnabled }); } else { - s_rateLimitersByChainSelector[chainSelector]._setTokenBucketConfig(configUpdate); + tokenBucket._setTokenBucketConfig(configUpdate); } emit RateLimiterConfigUpdated(chainSelector, configUpdate); } diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index 8fea06f904..b076b14033 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -3,10 +3,8 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; - import {IAny2EVMMultiOffRamp} from "../interfaces/IAny2EVMMultiOffRamp.sol"; import {IAny2EVMOffRamp} from "../interfaces/IAny2EVMOffRamp.sol"; - import {IMessageValidator} from "../interfaces/IMessageValidator.sol"; import {IMultiCommitStore} from "../interfaces/IMultiCommitStore.sol"; import {IPool} from "../interfaces/IPool.sol"; From 74717ed1ea2ece3902d4bfa667656c802ac7ea6f Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Mon, 27 May 2024 15:25:50 +0200 Subject: [PATCH 13/23] style: rename chainSelector to remoteChainSelector --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 42 ++++++++------- .../MultiAggregateRateLimiter.t.sol | 54 ++++++++++--------- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index fafea88fa6..abd3d6928a 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -24,8 +24,8 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { error ZeroAddressNotAllowed(); error ZeroChainSelectorNotAllowed(); - event RateLimiterConfigUpdated(uint64 indexed chainSelector, RateLimiterNoEvents.Config config); - event RateLimiterTokensConsumed(uint64 indexed chainSelector, uint256 tokens); + event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, RateLimiterNoEvents.Config config); + event RateLimiterTokensConsumed(uint64 indexed remoteChainSelector, uint256 tokens); event AdminSet(address newAdmin); event PriceRegistrySet(address newPriceRegistry); event TokenAggregateRateLimitAdded(address sourceToken, address destToken); @@ -47,7 +47,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Update args for a single rate limiter config update struct RateLimiterConfigArgs { - uint64 chainSelector; // Chain selector to set config for + uint64 remoteChainSelector; // Chain selector to set config for RateLimiterNoEvents.Config rateLimiterConfig; // Rate limiter config to set } @@ -63,7 +63,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { address internal s_priceRegistry; /// @notice Rate limiter token bucket states per chain - mapping(uint64 chainSelector => RateLimiterNoEvents.TokenBucket rateLimiter) s_rateLimitersByChainSelector; + mapping(uint64 remoteChainSelector => RateLimiterNoEvents.TokenBucket rateLimiter) s_rateLimitersByChainSelector; /// @param rateLimiterConfigs The RateLimiterNoEvents.Configs per chain containing the capacity and refill rate /// of the bucket @@ -92,7 +92,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { uint256 value; Client.EVMTokenAmount[] memory destTokenAmounts = message.destTokenAmounts; - for (uint256 i; i < destTokenAmounts.length; ++i) { + for (uint256 i = 0; i < destTokenAmounts.length; ++i) { if (s_rateLimitedTokensDestToSource.contains(destTokenAmounts[i].token)) { value += _getTokenValue(destTokenAmounts[i]); } @@ -107,11 +107,11 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } /// @notice Consumes value from the rate limiter bucket based on the token value given. - /// @param chainSelector chain selector to apply rate limit to + /// @param remoteChainSelector chain selector to apply rate limit to /// @param value consumed value - function _rateLimitValue(uint64 chainSelector, uint256 value) internal { - s_rateLimitersByChainSelector[chainSelector]._consume(value, address(0)); - emit RateLimiterTokensConsumed(chainSelector, value); + function _rateLimitValue(uint64 remoteChainSelector, uint256 value) internal { + s_rateLimitersByChainSelector[remoteChainSelector]._consume(value, address(0)); + emit RateLimiterTokensConsumed(remoteChainSelector, value); } /// @notice Retrieves the token value for a token using the PriceRegistry @@ -125,10 +125,14 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } /// @notice Gets the token bucket with its values for the block it was requested at. - /// @param chainSelector chain selector to retrieve state for + /// @param remoteChainSelector chain selector to retrieve state for /// @return The token bucket. - function currentRateLimiterState(uint64 chainSelector) external view returns (RateLimiterNoEvents.TokenBucket memory) { - return s_rateLimitersByChainSelector[chainSelector]._currentTokenBucketState(); + function currentRateLimiterState(uint64 remoteChainSelector) + external + view + returns (RateLimiterNoEvents.TokenBucket memory) + { + return s_rateLimitersByChainSelector[remoteChainSelector]._currentTokenBucketState(); } /// @notice Applies the provided rate limiter config updates. @@ -144,17 +148,17 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { for (uint256 i = 0; i < rateLimiterUpdates.length; ++i) { RateLimiterConfigArgs memory updateArgs = rateLimiterUpdates[i]; RateLimiterNoEvents.Config memory configUpdate = updateArgs.rateLimiterConfig; - uint64 chainSelector = updateArgs.chainSelector; + uint64 remoteChainSelector = updateArgs.remoteChainSelector; - if (chainSelector == 0) { + if (remoteChainSelector == 0) { revert ZeroChainSelectorNotAllowed(); } - RateLimiterNoEvents.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[chainSelector]; + RateLimiterNoEvents.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[remoteChainSelector]; if (tokenBucket.lastUpdated == 0) { // Token bucket needs to be newly added - s_rateLimitersByChainSelector[chainSelector] = RateLimiterNoEvents.TokenBucket({ + s_rateLimitersByChainSelector[remoteChainSelector] = RateLimiterNoEvents.TokenBucket({ rate: configUpdate.rate, capacity: configUpdate.capacity, tokens: configUpdate.capacity, @@ -164,7 +168,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } else { tokenBucket._setTokenBucketConfig(configUpdate); } - emit RateLimiterConfigUpdated(chainSelector, configUpdate); + emit RateLimiterConfigUpdated(remoteChainSelector, configUpdate); } } @@ -256,7 +260,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @param authorizedCallerArgs Callers to add and remove function _applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) internal { address[] memory addedCallers = authorizedCallerArgs.addedCallers; - for (uint256 i; i < addedCallers.length; ++i) { + for (uint256 i = 0; i < addedCallers.length; ++i) { address caller = addedCallers[i]; if (caller == address(0)) { @@ -268,7 +272,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } address[] memory removedCallers = authorizedCallerArgs.removedCallers; - for (uint256 i; i < removedCallers.length; ++i) { + for (uint256 i = 0; i < removedCallers.length; ++i) { address caller = removedCallers[i]; if (s_authorizedCallers[caller]) { diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 9b1c8c8c4b..29c846ff6d 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -40,11 +40,11 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1, + remoteChainSelector: CHAIN_SELECTOR_1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_2, + remoteChainSelector: CHAIN_SELECTOR_2, rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); @@ -121,11 +121,11 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1, + remoteChainSelector: CHAIN_SELECTOR_1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_2, + remoteChainSelector: CHAIN_SELECTOR_2, rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); @@ -410,7 +410,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1, + remoteChainSelector: CHAIN_SELECTOR_1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); @@ -467,13 +467,13 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1 + 1, + remoteChainSelector: CHAIN_SELECTOR_1 + 1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig ); vm.recordLogs(); @@ -483,7 +483,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(logEntries.length, 1); RateLimiterNoEvents.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); assertEq(BLOCK_TIME, bucket1.lastUpdated); } @@ -493,13 +493,13 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1 + 1, + remoteChainSelector: CHAIN_SELECTOR_1 + 1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig ); vm.recordLogs(); @@ -509,7 +509,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(logEntries.length, 1); RateLimiterNoEvents.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); assertEq(BLOCK_TIME, bucket1.lastUpdated); } @@ -520,13 +520,13 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega for (uint64 i; i < configUpdates.length; ++i) { configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1 + i + 1, + remoteChainSelector: CHAIN_SELECTOR_1 + i + 1, rateLimiterConfig: RateLimiterNoEvents.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) }); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[i].chainSelector, configUpdates[i].rateLimiterConfig + configUpdates[i].remoteChainSelector, configUpdates[i].rateLimiterConfig ); } @@ -538,7 +538,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega for (uint256 i; i < configUpdates.length; ++i) { RateLimiterNoEvents.TokenBucket memory bucket = - s_rateLimiter.currentRateLimiterState(configUpdates[i].chainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector); _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); assertEq(BLOCK_TIME, bucket.lastUpdated); } @@ -548,26 +548,26 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1, + remoteChainSelector: CHAIN_SELECTOR_1, rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); RateLimiterNoEvents.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); // Capacity equals tokens assertEq(bucket1.capacity, bucket1.tokens); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig ); vm.recordLogs(); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); vm.warp(BLOCK_TIME + 1); - bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); assertEq(BLOCK_TIME + 1, bucket1.lastUpdated); // Tokens < capacity since capacity doubled @@ -578,16 +578,16 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1, + remoteChainSelector: CHAIN_SELECTOR_1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); RateLimiterNoEvents.TokenBucket memory bucketPreUpdate = - s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].chainSelector, configUpdates[0].rateLimiterConfig + configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig ); vm.recordLogs(); @@ -595,7 +595,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega vm.warp(BLOCK_TIME + 1); RateLimiterNoEvents.TokenBucket memory bucketPostUpdate = - s_rateLimiter.currentRateLimiterState(configUpdates[0].chainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); _assertTokenBucketEquality(bucketPreUpdate, bucketPostUpdate); assertEq(BLOCK_TIME + 1, bucketPostUpdate.lastUpdated); } @@ -604,8 +604,10 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega function test_ZeroChainSelector_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = - MultiAggregateRateLimiter.RateLimiterConfigArgs({chainSelector: 0, rateLimiterConfig: RATE_LIMITER_CONFIG_1}); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: 0, + rateLimiterConfig: RATE_LIMITER_CONFIG_1 + }); vm.expectRevert(MultiAggregateRateLimiter.ZeroChainSelectorNotAllowed.selector); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); @@ -615,7 +617,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1 + 1, + remoteChainSelector: CHAIN_SELECTOR_1 + 1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); vm.startPrank(STRANGER); @@ -926,7 +928,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - chainSelector: CHAIN_SELECTOR_1, + remoteChainSelector: CHAIN_SELECTOR_1, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); configUpdates[0].rateLimiterConfig.isEnabled = false; From c0e441466ee96c6c4afb39be208b7fcceeb5eff9 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Mon, 27 May 2024 15:33:34 +0200 Subject: [PATCH 14/23] feat: remove admin from multi-arl --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 45 +----- .../MultiAggregateRateLimiterHelper.sol | 3 +- .../MultiAggregateRateLimiter.t.sol | 149 ++---------------- 3 files changed, 20 insertions(+), 177 deletions(-) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index abd3d6928a..21371f3978 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -26,7 +26,6 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, RateLimiterNoEvents.Config config); event RateLimiterTokensConsumed(uint64 indexed remoteChainSelector, uint256 tokens); - event AdminSet(address newAdmin); event PriceRegistrySet(address newPriceRegistry); event TokenAggregateRateLimitAdded(address sourceToken, address destToken); event TokenAggregateRateLimitRemoved(address sourceToken, address destToken); @@ -57,8 +56,6 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @dev Set of callers that can call the validation functions (this is required since the validations modify state) mapping(address authorizedCaller => bool isAuthorized) internal s_authorizedCallers; - /// @notice The address of the token limit admin that has the same permissions as the owner. - address internal s_admin; /// @notice The address of the PriceRegistry used to query token values for ratelimiting address internal s_priceRegistry; @@ -67,17 +64,14 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @param rateLimiterConfigs The RateLimiterNoEvents.Configs per chain containing the capacity and refill rate /// of the bucket - /// @param admin the admin address to set /// @param priceRegistry the price registry to set /// @param authorizedCallers the authorized callers to set constructor( RateLimiterConfigArgs[] memory rateLimiterConfigs, - address admin, address priceRegistry, address[] memory authorizedCallers ) { _applyRateLimiterConfigUpdates(rateLimiterConfigs); - _setAdmin(admin); _setPriceRegistry(priceRegistry); _applyAuthorizedCallerUpdates( AuthorizedCallerArgs({addedCallers: authorizedCallers, removedCallers: new address[](0)}) @@ -138,7 +132,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Applies the provided rate limiter config updates. /// @param rateLimiterUpdates Rate limiter updates /// @dev should only be callable by the owner or token limit admin - function applyRateLimiterConfigUpdates(RateLimiterConfigArgs[] memory rateLimiterUpdates) external onlyAdminOrOwner { + function applyRateLimiterConfigUpdates(RateLimiterConfigArgs[] memory rateLimiterUpdates) external onlyOwner { _applyRateLimiterConfigUpdates(rateLimiterUpdates); } @@ -192,10 +186,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Adds or removes tokens from being used in Aggregate Rate Limiting. /// @param removes - A list of one or more tokens to be removed. /// @param adds - A list of one or more tokens to be added. - function updateRateLimitTokens( - RateLimitToken[] memory removes, - RateLimitToken[] memory adds - ) external onlyAdminOrOwner { + function updateRateLimitTokens(RateLimitToken[] memory removes, RateLimitToken[] memory adds) external onlyOwner { for (uint256 i = 0; i < removes.length; ++i) { if (s_rateLimitedTokensDestToSource.remove(removes[i].destToken)) { emit TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); @@ -224,7 +215,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Sets the Price Registry address /// @param newPriceRegistry the address of the new PriceRegistry /// @dev precondition The address must be a non-zero address - function setPriceRegistry(address newPriceRegistry) external onlyAdminOrOwner { + function setPriceRegistry(address newPriceRegistry) external onlyOwner { _setPriceRegistry(newPriceRegistry); } @@ -252,7 +243,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Updates the callers that are authorized to call the message validation functions /// @param authorizedCallerArgs Callers to add and remove - function applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) external onlyAdminOrOwner { + function applyAuthorizedCallerUpdates(AuthorizedCallerArgs memory authorizedCallerArgs) external onlyOwner { _applyAuthorizedCallerUpdates(authorizedCallerArgs); } @@ -281,32 +272,4 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } } } - - /// @notice Gets the token limit admin address. - /// @return the token limit admin address. - function getTokenLimitAdmin() external view returns (address) { - return s_admin; - } - - /// @notice Sets the token limit admin address. - /// @param newAdmin the address of the new admin. - /// @dev setting this to address(0) indicates there is no active admin. - function setAdmin(address newAdmin) external onlyAdminOrOwner { - _setAdmin(newAdmin); - } - - /// @notice Sets the token limit admin address. - /// @param newAdmin the address of the new admin. - /// @dev setting this to address(0) indicates there is no active admin. - function _setAdmin(address newAdmin) internal { - s_admin = newAdmin; - emit AdminSet(newAdmin); - } - - /// @notice a modifier that allows the owner or the s_tokenLimitAdmin call the functions - /// it is applied to. - modifier onlyAdminOrOwner() { - if (msg.sender != owner() && msg.sender != s_admin) revert RateLimiterNoEvents.OnlyCallableByAdminOrOwner(); - _; - } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index b7808759b5..1e684d5ef0 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -8,10 +8,9 @@ import {Client} from "../../libraries/Client.sol"; contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { constructor( MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory rateLimiterConfigs, - address admin, address priceRegistry, address[] memory authorizedCallers - ) MultiAggregateRateLimiter(rateLimiterConfigs, admin, priceRegistry, authorizedCallers) {} + ) MultiAggregateRateLimiter(rateLimiterConfigs, priceRegistry, authorizedCallers) {} function rateLimitValue(uint64 chainSelector, uint256 value) public { _rateLimitValue(chainSelector, value); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 29c846ff6d..7dc111e08a 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -52,8 +52,7 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { authorizedCallers[0] = MOCK_OFFRAMP; authorizedCallers[1] = MOCK_ONRAMP; - s_rateLimiter = - new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, address(s_priceRegistry), authorizedCallers); } function _assertConfigWithTokenBucketEquality( @@ -85,14 +84,12 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup address[] memory authorizedCallers = new address[](0); vm.recordLogs(); - s_rateLimiter = - new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, address(s_priceRegistry), authorizedCallers); - // AdminSet + PriceRegistrySet + // PriceRegistrySet Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 2); + assertEq(logEntries.length, 1); - assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); assertEq(OWNER, s_rateLimiter.owner()); assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); } @@ -105,14 +102,12 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup authorizedCallers[1] = MOCK_ONRAMP; vm.recordLogs(); - s_rateLimiter = - new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, address(s_priceRegistry), authorizedCallers); - // AdminSet + PriceRegistrySet + 2 authorized caller sets + // PriceRegistrySet + 2 authorized caller sets Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 4); + assertEq(logEntries.length, 3); - assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); assertEq(OWNER, s_rateLimiter.owner()); assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); } @@ -148,10 +143,8 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup vm.expectEmit(); emit MultiAggregateRateLimiter.AuthorizedCallerAdded(MOCK_ONRAMP); - s_rateLimiter = - new MultiAggregateRateLimiterHelper(configUpdates, ADMIN, address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, address(s_priceRegistry), authorizedCallers); - assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); assertEq(OWNER, s_rateLimiter.owner()); assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); @@ -165,43 +158,6 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup } } -/// @notice #getTokenLimitAdmin -contract MultiAggregateRateLimiter_getTokenLimitAdmin is MultiAggregateRateLimiterSetup { - function test_GetTokenLimitAdmin_Success() public view { - assertEq(ADMIN, s_rateLimiter.getTokenLimitAdmin()); - } -} - -/// @notice #setAdmin -contract MultiAggregateRateLimiter_setAdmin is MultiAggregateRateLimiterSetup { - function test_Owner_Success() public { - vm.expectEmit(); - emit MultiAggregateRateLimiter.AdminSet(STRANGER); - - s_rateLimiter.setAdmin(STRANGER); - assertEq(STRANGER, s_rateLimiter.getTokenLimitAdmin()); - } - - function test_Admin_Success() public { - vm.startPrank(ADMIN); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.AdminSet(STRANGER); - - s_rateLimiter.setAdmin(STRANGER); - assertEq(STRANGER, s_rateLimiter.getTokenLimitAdmin()); - } - - // Reverts - - function test_OnlyOwnerOrAdmin_Revert() public { - vm.startPrank(STRANGER); - vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); - - s_rateLimiter.setAdmin(STRANGER); - } -} - /// @notice #setPriceRegistry contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiterSetup { function test_Owner_Success() public { @@ -214,23 +170,11 @@ contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiter assertEq(newAddress, s_rateLimiter.getPriceRegistry()); } - function test_Admin_Success() public { - vm.startPrank(ADMIN); - - address newAddress = address(42); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.PriceRegistrySet(newAddress); - - s_rateLimiter.setPriceRegistry(newAddress); - assertEq(newAddress, s_rateLimiter.getPriceRegistry()); - } - // Reverts - function test_OnlyOwnerOrAdmin_Revert() public { + function test_OnlyOwner_Revert() public { vm.startPrank(STRANGER); - vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + vm.expectRevert(bytes("Only callable by owner")); s_rateLimiter.setPriceRegistry(STRANGER); } @@ -350,26 +294,11 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim assertEq(logEntries.length, 0); } - function test_ChangedByAdmin_Success() public { - vm.startPrank(ADMIN); - - address[] memory addedCallers = new address[](0); - - address[] memory removedCallers = new address[](1); - removedCallers[0] = MOCK_OFFRAMP; - - s_rateLimiter.applyAuthorizedCallerUpdates( - MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) - ); - - assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); - } - // Reverts - function test_OnlyOwnerOrAdmin_Revert() public { + function test_OnlyOwner_Revert() public { vm.startPrank(STRANGER); - vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + vm.expectRevert(bytes("Only callable by owner")); address[] memory addedCallers = new address[](2); addedCallers[0] = address(42); @@ -488,32 +417,6 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(BLOCK_TIME, bucket1.lastUpdated); } - function test_SingleConfigByAdmin_Success() public { - vm.startPrank(ADMIN); - MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); - configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ - remoteChainSelector: CHAIN_SELECTOR_1 + 1, - rateLimiterConfig: RATE_LIMITER_CONFIG_1 - }); - - vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig - ); - - vm.recordLogs(); - s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - - Vm.Log[] memory logEntries = vm.getRecordedLogs(); - assertEq(logEntries.length, 1); - - RateLimiterNoEvents.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); - _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); - assertEq(BLOCK_TIME, bucket1.lastUpdated); - } - function test_MultipleConfigs_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](3); @@ -613,7 +516,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } - function test_OnlyCallableByAdminOrOwner_Revert() public { + function test_OnlyCallableByOwner_Revert() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ @@ -622,7 +525,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega }); vm.startPrank(STRANGER); - vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + vm.expectRevert(bytes("Only callable by owner")); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } } @@ -811,28 +714,6 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi assertEq(adds[1].destToken, destTokens[0]); } - function test_UpdateRateLimitTokensByAdmin_Success() public { - vm.startPrank(ADMIN); - - MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](2); - adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); - adds[1] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); - - for (uint256 i = 0; i < adds.length; ++i) { - vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); - } - - s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); - - (address[] memory sourceTokens, address[] memory destTokens) = s_rateLimiter.getAllRateLimitTokens(); - - for (uint256 i = 0; i < adds.length; ++i) { - assertEq(adds[i].sourceToken, sourceTokens[i]); - assertEq(adds[i].destToken, destTokens[i]); - } - } - // Reverts function test_ZeroSourceToken_Revert() public { @@ -856,7 +737,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi vm.startPrank(STRANGER); - vm.expectRevert(RateLimiterNoEvents.OnlyCallableByAdminOrOwner.selector); + vm.expectRevert(bytes("Only callable by owner")); s_rateLimiter.updateRateLimitTokens(addsAndRemoves, addsAndRemoves); } } From d09db46817ead74a531a75f51b377044ca339c63 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Mon, 27 May 2024 15:40:31 +0200 Subject: [PATCH 15/23] refactor: remove duplicated RateLimiter lib --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 26 +- .../ccip/libraries/RateLimiterNoEvents.sol | 152 --------- .../helpers/RateLimiterNoEventsHelper.sol | 36 --- .../test/libraries/RateLimiterNoEvents.t.sol | 297 ------------------ .../MultiAggregateRateLimiter.t.sol | 76 ++--- 5 files changed, 44 insertions(+), 543 deletions(-) delete mode 100644 contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol delete mode 100644 contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol delete mode 100644 contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 21371f3978..cd8129e832 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -7,14 +7,14 @@ import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; import {Client} from "./libraries/Client.sol"; -import {RateLimiterNoEvents} from "./libraries/RateLimiterNoEvents.sol"; +import {RateLimiter} from "./libraries/RateLimiter.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of /// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { - using RateLimiterNoEvents for RateLimiterNoEvents.TokenBucket; + using RateLimiter for RateLimiter.TokenBucket; using USDPriceWith18Decimals for uint224; using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; @@ -24,8 +24,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { error ZeroAddressNotAllowed(); error ZeroChainSelectorNotAllowed(); - event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, RateLimiterNoEvents.Config config); - event RateLimiterTokensConsumed(uint64 indexed remoteChainSelector, uint256 tokens); + event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, RateLimiter.Config config); event PriceRegistrySet(address newPriceRegistry); event TokenAggregateRateLimitAdded(address sourceToken, address destToken); event TokenAggregateRateLimitRemoved(address sourceToken, address destToken); @@ -47,7 +46,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Update args for a single rate limiter config update struct RateLimiterConfigArgs { uint64 remoteChainSelector; // Chain selector to set config for - RateLimiterNoEvents.Config rateLimiterConfig; // Rate limiter config to set + RateLimiter.Config rateLimiterConfig; // Rate limiter config to set } /// @dev Tokens that should be included in Aggregate Rate Limiting (from dest -> source) @@ -60,9 +59,9 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { address internal s_priceRegistry; /// @notice Rate limiter token bucket states per chain - mapping(uint64 remoteChainSelector => RateLimiterNoEvents.TokenBucket rateLimiter) s_rateLimitersByChainSelector; + mapping(uint64 remoteChainSelector => RateLimiter.TokenBucket rateLimiter) s_rateLimitersByChainSelector; - /// @param rateLimiterConfigs The RateLimiterNoEvents.Configs per chain containing the capacity and refill rate + /// @param rateLimiterConfigs The RateLimiter.Configs per chain containing the capacity and refill rate /// of the bucket /// @param priceRegistry the price registry to set /// @param authorizedCallers the authorized callers to set @@ -105,7 +104,6 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @param value consumed value function _rateLimitValue(uint64 remoteChainSelector, uint256 value) internal { s_rateLimitersByChainSelector[remoteChainSelector]._consume(value, address(0)); - emit RateLimiterTokensConsumed(remoteChainSelector, value); } /// @notice Retrieves the token value for a token using the PriceRegistry @@ -121,11 +119,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Gets the token bucket with its values for the block it was requested at. /// @param remoteChainSelector chain selector to retrieve state for /// @return The token bucket. - function currentRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiterNoEvents.TokenBucket memory) - { + function currentRateLimiterState(uint64 remoteChainSelector) external view returns (RateLimiter.TokenBucket memory) { return s_rateLimitersByChainSelector[remoteChainSelector]._currentTokenBucketState(); } @@ -141,18 +135,18 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { function _applyRateLimiterConfigUpdates(RateLimiterConfigArgs[] memory rateLimiterUpdates) internal { for (uint256 i = 0; i < rateLimiterUpdates.length; ++i) { RateLimiterConfigArgs memory updateArgs = rateLimiterUpdates[i]; - RateLimiterNoEvents.Config memory configUpdate = updateArgs.rateLimiterConfig; + RateLimiter.Config memory configUpdate = updateArgs.rateLimiterConfig; uint64 remoteChainSelector = updateArgs.remoteChainSelector; if (remoteChainSelector == 0) { revert ZeroChainSelectorNotAllowed(); } - RateLimiterNoEvents.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[remoteChainSelector]; + RateLimiter.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[remoteChainSelector]; if (tokenBucket.lastUpdated == 0) { // Token bucket needs to be newly added - s_rateLimitersByChainSelector[remoteChainSelector] = RateLimiterNoEvents.TokenBucket({ + s_rateLimitersByChainSelector[remoteChainSelector] = RateLimiter.TokenBucket({ rate: configUpdate.rate, capacity: configUpdate.capacity, tokens: configUpdate.capacity, diff --git a/contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol b/contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol deleted file mode 100644 index baaaf4a63a..0000000000 --- a/contracts/src/v0.8/ccip/libraries/RateLimiterNoEvents.sol +++ /dev/null @@ -1,152 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -/// @notice Implements Token Bucket rate limiting. -/// @dev uint128 is safe for rate limiter state. -/// For USD value rate limiting, it can adequately store USD value in 18 decimals. -/// For ERC20 token amount rate limiting, all tokens that will be listed will have at most -/// a supply of uint128.max tokens, and it will therefore not overflow the bucket. -/// In exceptional scenarios where tokens consumed may be larger than uint128, -/// e.g. compromised issuer, an enabled RateLimiter will check and revert. -/// This version of the RateLimiter delegates event emissions to the consumer. -library RateLimiterNoEvents { - error BucketOverfilled(); - error OnlyCallableByAdminOrOwner(); - error TokenMaxCapacityExceeded(uint256 capacity, uint256 requested, address tokenAddress); - error TokenRateLimitReached(uint256 minWaitInSeconds, uint256 available, address tokenAddress); - error AggregateValueMaxCapacityExceeded(uint256 capacity, uint256 requested); - error AggregateValueRateLimitReached(uint256 minWaitInSeconds, uint256 available); - error InvalidRatelimitRate(Config rateLimiterConfig); - error DisabledNonZeroRateLimit(Config config); - error RateLimitMustBeDisabled(); - - struct TokenBucket { - uint128 tokens; // ──────╮ Current number of tokens that are in the bucket. - uint32 lastUpdated; // │ Timestamp in seconds of the last token refill, good for 100+ years. - bool isEnabled; // ──────╯ Indication whether the rate limiting is enabled or not - uint128 capacity; // ────╮ Maximum number of tokens that can be in the bucket. - uint128 rate; // ────────╯ Number of tokens per second that the bucket is refilled. - } - - struct Config { - bool isEnabled; // Indication whether the rate limiting should be enabled - uint128 capacity; // ────╮ Specifies the capacity of the rate limiter - uint128 rate; // ───────╯ Specifies the rate of the rate limiter - } - - /// @notice _consume removes the given tokens from the pool, lowering the - /// rate tokens allowed to be consumed for subsequent calls. - /// @param requestTokens The total tokens to be consumed from the bucket. - /// @param tokenAddress The token to consume capacity for, use 0x0 to indicate aggregate value capacity. - /// @dev Reverts when requestTokens exceeds bucket capacity or available tokens in the bucket - /// @dev emits removal of requestTokens if requestTokens is > 0 - function _consume(TokenBucket storage s_bucket, uint256 requestTokens, address tokenAddress) internal { - // If there is no value to remove or rate limiting is turned off, skip this step to reduce gas usage - if (!s_bucket.isEnabled || requestTokens == 0) { - return; - } - - uint256 tokens = s_bucket.tokens; - uint256 capacity = s_bucket.capacity; - uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; - - if (timeDiff != 0) { - if (tokens > capacity) revert BucketOverfilled(); - - // Refill tokens when arriving at a new block time - tokens = _calculateRefill(capacity, tokens, timeDiff, s_bucket.rate); - - s_bucket.lastUpdated = uint32(block.timestamp); - } - - if (capacity < requestTokens) { - // Token address 0 indicates consuming aggregate value rate limit capacity. - if (tokenAddress == address(0)) revert AggregateValueMaxCapacityExceeded(capacity, requestTokens); - revert TokenMaxCapacityExceeded(capacity, requestTokens, tokenAddress); - } - if (tokens < requestTokens) { - uint256 rate = s_bucket.rate; - // Wait required until the bucket is refilled enough to accept this value, round up to next higher second - // Consume is not guaranteed to succeed after wait time passes if there is competing traffic. - // This acts as a lower bound of wait time. - uint256 minWaitInSeconds = ((requestTokens - tokens) + (rate - 1)) / rate; - - if (tokenAddress == address(0)) revert AggregateValueRateLimitReached(minWaitInSeconds, tokens); - revert TokenRateLimitReached(minWaitInSeconds, tokens, tokenAddress); - } - tokens -= requestTokens; - - // Downcast is safe here, as tokens is not larger than capacity - s_bucket.tokens = uint128(tokens); - } - - /// @notice Gets the token bucket with its values for the block it was requested at. - /// @return The token bucket. - function _currentTokenBucketState(TokenBucket memory bucket) internal view returns (TokenBucket memory) { - // We update the bucket to reflect the status at the exact time of the - // call. This means we might need to refill a part of the bucket based - // on the time that has passed since the last update. - bucket.tokens = - uint128(_calculateRefill(bucket.capacity, bucket.tokens, block.timestamp - bucket.lastUpdated, bucket.rate)); - bucket.lastUpdated = uint32(block.timestamp); - return bucket; - } - - /// @notice Sets the rate limited config. - /// @param s_bucket The token bucket - /// @param config The new config - function _setTokenBucketConfig(TokenBucket storage s_bucket, Config memory config) internal { - // First update the bucket to make sure the proper rate is used for all the time - // up until the config change. - uint256 timeDiff = block.timestamp - s_bucket.lastUpdated; - if (timeDiff != 0) { - s_bucket.tokens = uint128(_calculateRefill(s_bucket.capacity, s_bucket.tokens, timeDiff, s_bucket.rate)); - - s_bucket.lastUpdated = uint32(block.timestamp); - } - - s_bucket.tokens = uint128(_min(config.capacity, s_bucket.tokens)); - s_bucket.isEnabled = config.isEnabled; - s_bucket.capacity = config.capacity; - s_bucket.rate = config.rate; - } - - /// @notice Validates the token bucket config - function _validateTokenBucketConfig(Config memory config, bool mustBeDisabled) internal pure { - if (config.isEnabled) { - if (config.rate >= config.capacity || config.rate == 0) { - revert InvalidRatelimitRate(config); - } - if (mustBeDisabled) { - revert RateLimitMustBeDisabled(); - } - } else { - if (config.rate != 0 || config.capacity != 0) { - revert DisabledNonZeroRateLimit(config); - } - } - } - - /// @notice Calculate refilled tokens - /// @param capacity bucket capacity - /// @param tokens current bucket tokens - /// @param timeDiff block time difference since last refill - /// @param rate bucket refill rate - /// @return the value of tokens after refill - function _calculateRefill( - uint256 capacity, - uint256 tokens, - uint256 timeDiff, - uint256 rate - ) private pure returns (uint256) { - return _min(capacity, tokens + timeDiff * rate); - } - - /// @notice Return the smallest of two integers - /// @param a first int - /// @param b second int - /// @return smallest - function _min(uint256 a, uint256 b) internal pure returns (uint256) { - return a < b ? a : b; - } -} diff --git a/contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol b/contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol deleted file mode 100644 index b8dbff9f30..0000000000 --- a/contracts/src/v0.8/ccip/test/helpers/RateLimiterNoEventsHelper.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; - -contract RateLimiterNoEventsHelper { - using RateLimiterNoEvents for RateLimiterNoEvents.TokenBucket; - - RateLimiterNoEvents.TokenBucket internal s_rateLimiter; - - constructor(RateLimiterNoEvents.Config memory config) { - s_rateLimiter = RateLimiterNoEvents.TokenBucket({ - rate: config.rate, - capacity: config.capacity, - tokens: config.capacity, - lastUpdated: uint32(block.timestamp), - isEnabled: config.isEnabled - }); - } - - function consume(uint256 requestTokens, address tokenAddress) external { - s_rateLimiter._consume(requestTokens, tokenAddress); - } - - function currentTokenBucketState() external view returns (RateLimiterNoEvents.TokenBucket memory) { - return s_rateLimiter._currentTokenBucketState(); - } - - function setTokenBucketConfig(RateLimiterNoEvents.Config memory config) external { - s_rateLimiter._setTokenBucketConfig(config); - } - - function getRateLimiter() external view returns (RateLimiterNoEvents.TokenBucket memory) { - return s_rateLimiter; - } -} diff --git a/contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol b/contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol deleted file mode 100644 index a3cb1c896a..0000000000 --- a/contracts/src/v0.8/ccip/test/libraries/RateLimiterNoEvents.t.sol +++ /dev/null @@ -1,297 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.24; - -import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; -import {BaseTest} from "../BaseTest.t.sol"; -import {RateLimiterNoEventsHelper} from "../helpers/RateLimiterNoEventsHelper.sol"; - -contract RateLimiterNoEventsSetup is BaseTest { - RateLimiterNoEventsHelper internal s_helper; - RateLimiterNoEvents.Config internal s_config; - - function setUp() public virtual override { - BaseTest.setUp(); - - s_config = RateLimiterNoEvents.Config({isEnabled: true, rate: 5, capacity: 100}); - s_helper = new RateLimiterNoEventsHelper(s_config); - } -} - -contract RateLimiterNoEvents_constructor is RateLimiterNoEventsSetup { - function test_Constructor_Success() public view { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - } -} - -/// @notice #setTokenBucketConfig -contract RateLimiterNoEvents_setTokenBucketConfig is RateLimiterNoEventsSetup { - function test_SetRateLimiterNoEventsConfig_Success() public { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - - s_config = RateLimiterNoEvents.Config({ - isEnabled: true, - rate: uint128(rateLimiter.rate * 2), - capacity: rateLimiter.capacity * 8 - }); - - s_helper.setTokenBucketConfig(s_config); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity / 8, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - } -} - -/// @notice #currentTokenBucketState -contract RateLimiterNoEvents_currentTokenBucketState is RateLimiterNoEventsSetup { - function test_CurrentTokenBucketState_Success() public { - RateLimiterNoEvents.TokenBucket memory bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - s_config = - RateLimiterNoEvents.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); - - s_helper.setTokenBucketConfig(s_config); - - bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 8, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - } - - function test_Refill_Success() public { - RateLimiterNoEvents.TokenBucket memory bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - s_config = - RateLimiterNoEvents.Config({isEnabled: true, rate: uint128(bucket.rate * 2), capacity: bucket.capacity * 8}); - - s_helper.setTokenBucketConfig(s_config); - - bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.rate, bucket.rate); - assertEq(s_config.capacity, bucket.capacity); - assertEq(s_config.capacity / 8, bucket.tokens); - assertEq(s_config.isEnabled, bucket.isEnabled); - assertEq(BLOCK_TIME, bucket.lastUpdated); - - uint256 warpTime = 4; - vm.warp(BLOCK_TIME + warpTime); - - bucket = s_helper.currentTokenBucketState(); - - assertEq(s_config.capacity / 8 + warpTime * s_config.rate, bucket.tokens); - - vm.warp(BLOCK_TIME + warpTime * 100); - - // Bucket overflow - bucket = s_helper.currentTokenBucketState(); - assertEq(s_config.capacity, bucket.tokens); - } -} - -/// @notice #consume -contract RateLimiterNoEvents_consume is RateLimiterNoEventsSetup { - address internal s_token = address(100); - - function test_ConsumeAggregateValue_Success() public { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - - uint256 requestTokens = 50; - - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - } - - function test_ConsumeTokens_Success() public { - uint256 requestTokens = 50; - - s_helper.consume(requestTokens, s_token); - } - - function test_Refill_Success() public { - uint256 requestTokens = 50; - - s_helper.consume(requestTokens, address(0)); - - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity - requestTokens, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME, rateLimiter.lastUpdated); - - uint256 warpTime = 4; - vm.warp(BLOCK_TIME + warpTime); - - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(s_config.capacity - requestTokens * 2 + warpTime * s_config.rate, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - assertEq(BLOCK_TIME + warpTime, rateLimiter.lastUpdated); - } - - function test_ConsumeUnlimited_Success() public { - s_helper.consume(0, address(0)); - - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.capacity, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - - RateLimiterNoEvents.Config memory disableConfig = - RateLimiterNoEvents.Config({isEnabled: false, rate: 0, capacity: 0}); - - s_helper.setTokenBucketConfig(disableConfig); - - uint256 requestTokens = 50; - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(disableConfig.capacity, rateLimiter.tokens); - assertEq(disableConfig.isEnabled, rateLimiter.isEnabled); - - s_helper.setTokenBucketConfig(s_config); - - vm.expectRevert(abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 10, 0)); - s_helper.consume(requestTokens, address(0)); - - rateLimiter = s_helper.getRateLimiter(); - assertEq(s_config.rate, rateLimiter.rate); - assertEq(s_config.capacity, rateLimiter.capacity); - assertEq(0, rateLimiter.tokens); - assertEq(s_config.isEnabled, rateLimiter.isEnabled); - } - - // Reverts - - function test_AggregateValueMaxCapacityExceeded_Revert() public { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1 - ) - ); - s_helper.consume(rateLimiter.capacity + 1, address(0)); - } - - function test_TokenMaxCapacityExceeded_Revert() public { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiterNoEvents.TokenMaxCapacityExceeded.selector, rateLimiter.capacity, rateLimiter.capacity + 1, s_token - ) - ); - s_helper.consume(rateLimiter.capacity + 1, s_token); - } - - function test_ConsumingMoreThanUint128_Revert() public { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - uint256 request = uint256(type(uint128).max) + 1; - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, rateLimiter.capacity, request - ) - ); - s_helper.consume(request, address(0)); - } - - function test_AggregateValueRateLimitReached_Revert() public { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - uint256 overLimit = 20; - uint256 requestTokens1 = rateLimiter.capacity / 2; - uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; - - uint256 waitInSeconds = overLimit / rateLimiter.rate; - - s_helper.consume(requestTokens1, address(0)); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiterNoEvents.AggregateValueRateLimitReached.selector, - waitInSeconds, - rateLimiter.capacity - requestTokens1 - ) - ); - s_helper.consume(requestTokens2, address(0)); - } - - function test_TokenRateLimitReached_Revert() public { - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - uint256 overLimit = 20; - uint256 requestTokens1 = rateLimiter.capacity / 2; - uint256 requestTokens2 = rateLimiter.capacity / 2 + overLimit; - - uint256 waitInSeconds = overLimit / rateLimiter.rate; - - s_helper.consume(requestTokens1, s_token); - - vm.expectRevert( - abi.encodeWithSelector( - RateLimiterNoEvents.TokenRateLimitReached.selector, - waitInSeconds, - rateLimiter.capacity - requestTokens1, - s_token - ) - ); - s_helper.consume(requestTokens2, s_token); - } - - function test_RateLimitReachedOverConsecutiveBlocks_Revert() public { - uint256 initBlockTime = BLOCK_TIME + 10000; - vm.warp(initBlockTime); - - RateLimiterNoEvents.TokenBucket memory rateLimiter = s_helper.getRateLimiter(); - - s_helper.consume(rateLimiter.capacity, address(0)); - - vm.warp(initBlockTime + 1); - - // Over rate limit by 1, force 1 second wait - uint256 overLimit = 1; - - vm.expectRevert( - abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 1, rateLimiter.rate) - ); - s_helper.consume(rateLimiter.rate + overLimit, address(0)); - } -} diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 7dc111e08a..d1f03a2594 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -6,7 +6,7 @@ import {Vm} from "forge-std/Vm.sol"; import {MultiAggregateRateLimiter} from "../../MultiAggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {RateLimiterNoEvents} from "../../libraries/RateLimiterNoEvents.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {BaseTest} from "../BaseTest.t.sol"; import {MultiAggregateRateLimiterHelper} from "../helpers/MultiAggregateRateLimiterHelper.sol"; import {PriceRegistrySetup} from "../priceRegistry/PriceRegistry.t.sol"; @@ -22,10 +22,8 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { uint64 internal constant CHAIN_SELECTOR_1 = 5009297550715157269; uint64 internal constant CHAIN_SELECTOR_2 = 4949039107694359620; - RateLimiterNoEvents.Config internal RATE_LIMITER_CONFIG_1 = - RateLimiterNoEvents.Config({isEnabled: true, rate: 5, capacity: 100}); - RateLimiterNoEvents.Config internal RATE_LIMITER_CONFIG_2 = - RateLimiterNoEvents.Config({isEnabled: true, rate: 10, capacity: 200}); + RateLimiter.Config internal RATE_LIMITER_CONFIG_1 = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); + RateLimiter.Config internal RATE_LIMITER_CONFIG_2 = RateLimiter.Config({isEnabled: true, rate: 10, capacity: 200}); address internal immutable MOCK_OFFRAMP = address(1111); address internal immutable MOCK_ONRAMP = address(1112); @@ -56,8 +54,8 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { } function _assertConfigWithTokenBucketEquality( - RateLimiterNoEvents.Config memory config, - RateLimiterNoEvents.TokenBucket memory tokenBucket + RateLimiter.Config memory config, + RateLimiter.TokenBucket memory tokenBucket ) internal pure { assertEq(config.rate, tokenBucket.rate); assertEq(config.capacity, tokenBucket.capacity); @@ -66,8 +64,8 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { } function _assertTokenBucketEquality( - RateLimiterNoEvents.TokenBucket memory tokenBucketA, - RateLimiterNoEvents.TokenBucket memory tokenBucketB + RateLimiter.TokenBucket memory tokenBucketA, + RateLimiter.TokenBucket memory tokenBucketB ) internal pure { assertEq(tokenBucketA.rate, tokenBucketB.rate); assertEq(tokenBucketA.capacity, tokenBucketB.capacity); @@ -148,11 +146,11 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup assertEq(OWNER, s_rateLimiter.owner()); assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); - RateLimiterNoEvents.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketSrcChain1); assertEq(BLOCK_TIME, bucketSrcChain1.lastUpdated); - RateLimiterNoEvents.TokenBucket memory bucketSrcChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + RateLimiter.TokenBucket memory bucketSrcChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_2, bucketSrcChain2); assertEq(BLOCK_TIME, bucketSrcChain2.lastUpdated); } @@ -326,7 +324,7 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim /// @notice #getTokenBucket contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { function test_GetTokenBucket_Success() public view { - RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.tokens); @@ -345,7 +343,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); @@ -411,8 +409,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega Vm.Log[] memory logEntries = vm.getRecordedLogs(); assertEq(logEntries.length, 1); - RateLimiterNoEvents.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); + RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); assertEq(BLOCK_TIME, bucket1.lastUpdated); } @@ -424,7 +421,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega for (uint64 i; i < configUpdates.length; ++i) { configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1 + i + 1, - rateLimiterConfig: RateLimiterNoEvents.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) + rateLimiterConfig: RateLimiter.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) }); vm.expectEmit(); @@ -440,7 +437,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega assertEq(logEntries.length, configUpdates.length); for (uint256 i; i < configUpdates.length; ++i) { - RateLimiterNoEvents.TokenBucket memory bucket = + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector); _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); assertEq(BLOCK_TIME, bucket.lastUpdated); @@ -455,8 +452,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); - RateLimiterNoEvents.TokenBucket memory bucket1 = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); + RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); // Capacity equals tokens assertEq(bucket1.capacity, bucket1.tokens); @@ -485,7 +481,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); - RateLimiterNoEvents.TokenBucket memory bucketPreUpdate = + RateLimiter.TokenBucket memory bucketPreUpdate = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); vm.expectEmit(); @@ -497,7 +493,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); vm.warp(BLOCK_TIME + 1); - RateLimiterNoEvents.TokenBucket memory bucketPostUpdate = + RateLimiter.TokenBucket memory bucketPostUpdate = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); _assertTokenBucketEquality(bucketPreUpdate, bucketPostUpdate); assertEq(BLOCK_TIME + 1, bucketPostUpdate.lastUpdated); @@ -542,14 +538,14 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, value); + emit RateLimiter.TokensConsumed(value); vm.resumeGasMetering(); s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); vm.pauseGasMetering(); // Get the updated bucket status - RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); // Assert the proper value has been taken out of the bucket assertEq(bucket.capacity - value, bucket.tokens); @@ -557,7 +553,7 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS // Expect a revert when we try, with a wait time. uint256 waitTime = 4; vm.expectRevert( - abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) + abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) ); s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); @@ -581,15 +577,15 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, value); + emit RateLimiter.TokensConsumed(value); vm.resumeGasMetering(); s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); vm.pauseGasMetering(); // Get the updated bucket status - RateLimiterNoEvents.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); - RateLimiterNoEvents.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); // Assert the proper value has been taken out of the bucket assertEq(bucket1.capacity - value, bucket1.tokens); @@ -597,7 +593,7 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS assertEq(bucket2.capacity, bucket2.tokens); vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_2, value); + emit RateLimiter.TokensConsumed(value); vm.resumeGasMetering(); s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_2, value); @@ -614,16 +610,14 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS // Reverts function test_AggregateValueMaxCapacityExceeded_Revert() public { - RateLimiterNoEvents.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); uint256 numberOfTokens = 100; uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; vm.expectRevert( abi.encodeWithSelector( - RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, - bucket.capacity, - (numberOfTokens * TOKEN_PRICE) / 1e18 + RateLimiter.AggregateValueMaxCapacityExceeded.selector, bucket.capacity, (numberOfTokens * TOKEN_PRICE) / 1e18 ) ); s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); @@ -782,7 +776,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate // 3 tokens * TOKEN_PRICE + 1 token * (2 * TOKEN_PRICE) vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, (5 * TOKEN_PRICE) / 1e18); + emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } @@ -800,7 +794,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate vm.startPrank(MOCK_OFFRAMP); vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_1, (5 * TOKEN_PRICE) / 1e18); + emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } @@ -841,15 +835,15 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Chain 1 changed - RateLimiterNoEvents.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); // Chain 2 unchanged - RateLimiterNoEvents.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); assertEq(bucketChain2.capacity, bucketChain2.tokens); vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterTokensConsumed(CHAIN_SELECTOR_2, (4 * TOKEN_PRICE) / 1e18); + emit RateLimiter.TokensConsumed((4 * TOKEN_PRICE) / 1e18); s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); @@ -872,12 +866,12 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) - vm.expectRevert(abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 12, 20)); + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 12, 20)); s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Remaining capacity: 20 -> 35 (need to wait 9 more blocks) vm.warp(BLOCK_TIME + 3); - vm.expectRevert(abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueRateLimitReached.selector, 9, 35)); + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 9, 35)); s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Remaining capacity: 35 -> 80 (can fit exactly 80) @@ -895,9 +889,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 30}); uint256 totalValue = (80 * TOKEN_PRICE + 2 * (30 * TOKEN_PRICE)) / 1e18; - vm.expectRevert( - abi.encodeWithSelector(RateLimiterNoEvents.AggregateValueMaxCapacityExceeded.selector, 100, totalValue) - ); + vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, 100, totalValue)); s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } From 4183828c60bc20a08dd6ac4aaf9f1af181096432 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Mon, 27 May 2024 16:11:05 +0200 Subject: [PATCH 16/23] refactor: convert authorized callers to set with getter --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 20 +++--- .../MultiAggregateRateLimiter.t.sol | 62 ++++++++++--------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index cd8129e832..3b06d26995 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -6,6 +6,7 @@ import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; +import {EnumerableSet} from "./../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/structs/EnumerableSet.sol"; import {Client} from "./libraries/Client.sol"; import {RateLimiter} from "./libraries/RateLimiter.sol"; import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; @@ -13,10 +14,13 @@ import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of /// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). +/// The contract is a standalone multi-lane message validator contract, which can be called by authorized +/// ramp contracts to apply rate limit changes to lanes, and revert when the rate limits get breached. contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { using RateLimiter for RateLimiter.TokenBucket; using USDPriceWith18Decimals for uint224; using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; + using EnumerableSet for EnumerableSet.AddressSet; error UnauthorizedCaller(address caller); error PriceNotFoundForToken(address token); @@ -53,7 +57,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensDestToSource; /// @dev Set of callers that can call the validation functions (this is required since the validations modify state) - mapping(address authorizedCaller => bool isAuthorized) internal s_authorizedCallers; + EnumerableSet.AddressSet internal s_authorizedCallers; /// @notice The address of the PriceRegistry used to query token values for ratelimiting address internal s_priceRegistry; @@ -79,7 +83,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @inheritdoc IMessageValidator function validateIncomingMessage(Client.Any2EVMMessage memory message) external { - if (!s_authorizedCallers[msg.sender]) { + if (!s_authorizedCallers.contains(msg.sender)) { revert UnauthorizedCaller(msg.sender); } @@ -229,10 +233,9 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { // │ Access │ // ================================================================ - /// @param caller Address to check whether it is an authorized caller - /// @return flag whether the caller is an authorized caller - function isAuthorizedCaller(address caller) external view returns (bool) { - return s_authorizedCallers[caller]; + /// @return authorizedCallers Returns all callers that are authorized to call the validation functions + function getAllAuthorizedCallers() external view returns (address[] memory) { + return s_authorizedCallers.values(); } /// @notice Updates the callers that are authorized to call the message validation functions @@ -252,7 +255,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { revert ZeroAddressNotAllowed(); } - s_authorizedCallers[caller] = true; + s_authorizedCallers.add(caller); emit AuthorizedCallerAdded(caller); } @@ -260,8 +263,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { for (uint256 i = 0; i < removedCallers.length; ++i) { address caller = removedCallers[i]; - if (s_authorizedCallers[caller]) { - delete s_authorizedCallers[caller]; + if (s_authorizedCallers.remove(caller)) { emit AuthorizedCallerRemoved(caller); } } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index d1f03a2594..9206db6a59 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -28,6 +28,8 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { address internal immutable MOCK_OFFRAMP = address(1111); address internal immutable MOCK_ONRAMP = address(1112); + address[] internal s_authorizedCallers; + function setUp() public virtual override(BaseTest, PriceRegistrySetup) { BaseTest.setUp(); PriceRegistrySetup.setUp(); @@ -46,11 +48,11 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); - address[] memory authorizedCallers = new address[](2); - authorizedCallers[0] = MOCK_OFFRAMP; - authorizedCallers[1] = MOCK_ONRAMP; + s_authorizedCallers = new address[](2); + s_authorizedCallers[0] = MOCK_OFFRAMP; + s_authorizedCallers[1] = MOCK_ONRAMP; - s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(configUpdates, address(s_priceRegistry), s_authorizedCallers); } function _assertConfigWithTokenBucketEquality( @@ -74,7 +76,6 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { } } -/// @notice #constructor contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup { function test_ConstructorNoAuthorizedCallers_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = @@ -156,7 +157,6 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup } } -/// @notice #setPriceRegistry contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiterSetup { function test_Owner_Success() public { address newAddress = address(42); @@ -183,7 +183,6 @@ contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiter } } -/// @notice #setPriceRegistry contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLimiterSetup { function test_OnlyAdd_Success() public { address[] memory addedCallers = new address[](2); @@ -192,8 +191,7 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim address[] memory removedCallers = new address[](0); - assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); - assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); + assertEq(s_rateLimiter.getAllAuthorizedCallers(), s_authorizedCallers); vm.expectEmit(); emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[0]); @@ -204,17 +202,22 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) ); - assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); - assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); + address[] memory expectedCallers = new address[](4); + expectedCallers[0] = s_authorizedCallers[0]; + expectedCallers[1] = s_authorizedCallers[1]; + expectedCallers[2] = addedCallers[0]; + expectedCallers[3] = addedCallers[1]; + + assertEq(s_rateLimiter.getAllAuthorizedCallers(), expectedCallers); } function test_OnlyRemove_Success() public { address[] memory addedCallers = new address[](0); address[] memory removedCallers = new address[](1); - removedCallers[0] = MOCK_OFFRAMP; + removedCallers[0] = s_authorizedCallers[0]; - assertTrue(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + assertEq(s_rateLimiter.getAllAuthorizedCallers(), s_authorizedCallers); vm.expectEmit(); emit MultiAggregateRateLimiter.AuthorizedCallerRemoved(removedCallers[0]); @@ -223,7 +226,10 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) ); - assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + address[] memory expectedCallers = new address[](1); + expectedCallers[0] = s_authorizedCallers[1]; + + assertEq(s_rateLimiter.getAllAuthorizedCallers(), expectedCallers); } function test_AddAndRemove_Success() public { @@ -232,11 +238,9 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim addedCallers[1] = address(43); address[] memory removedCallers = new address[](1); - removedCallers[0] = MOCK_OFFRAMP; + removedCallers[0] = s_authorizedCallers[0]; - assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); - assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); - assertTrue(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + assertEq(s_rateLimiter.getAllAuthorizedCallers(), s_authorizedCallers); vm.expectEmit(); emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[0]); @@ -249,9 +253,13 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) ); - assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); - assertTrue(s_rateLimiter.isAuthorizedCaller(addedCallers[1])); - assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + // Order of the set changes on removal + address[] memory expectedCallers = new address[](3); + expectedCallers[0] = addedCallers[1]; + expectedCallers[1] = s_authorizedCallers[1]; + expectedCallers[2] = addedCallers[0]; + + assertEq(s_rateLimiter.getAllAuthorizedCallers(), expectedCallers); } function test_AddThenRemove_Success() public { @@ -261,7 +269,7 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim address[] memory removedCallers = new address[](1); removedCallers[0] = address(42); - assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + assertEq(s_rateLimiter.getAllAuthorizedCallers(), s_authorizedCallers); vm.expectEmit(); emit MultiAggregateRateLimiter.AuthorizedCallerAdded(addedCallers[0]); @@ -272,7 +280,7 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) ); - assertFalse(s_rateLimiter.isAuthorizedCaller(addedCallers[0])); + assertEq(s_rateLimiter.getAllAuthorizedCallers(), s_authorizedCallers); } function test_SkipRemove_Success() public { @@ -286,7 +294,7 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim MultiAggregateRateLimiter.AuthorizedCallerArgs({addedCallers: addedCallers, removedCallers: removedCallers}) ); - assertFalse(s_rateLimiter.isAuthorizedCaller(removedCallers[0])); + assertEq(s_rateLimiter.getAllAuthorizedCallers(), s_authorizedCallers); Vm.Log[] memory logEntries = vm.getRecordedLogs(); assertEq(logEntries.length, 0); @@ -321,7 +329,6 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim } } -/// @notice #getTokenBucket contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { function test_GetTokenBucket_Success() public view { RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); @@ -377,7 +384,6 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe } } -/// @notice #applyRateLimiterConfigUpdates contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggregateRateLimiterSetup { function test_ZeroConfigs_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = @@ -526,7 +532,6 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega } } -// /// @notice #_rateLimitValue contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterSetup { function test_RateLimitValue_Success_gas() public { vm.pauseGasMetering(); @@ -624,7 +629,6 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS } } -/// @notice #_getTokenValue contract MultiAggregateRateLimiter__getTokenValue is MultiAggregateRateLimiterSetup { function test_GetTokenValue_Success() public view { uint256 numberOfTokens = 10; @@ -643,7 +647,6 @@ contract MultiAggregateRateLimiter__getTokenValue is MultiAggregateRateLimiterSe } } -/// @notice #updateRateLimitTokens contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLimiterSetup { function setUp() public virtual override { super.setUp(); @@ -736,7 +739,6 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi } } -/// @notice #validateIncomingMessage contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRateLimiterSetup { address internal immutable MOCK_RECEIVER = address(1113); From 184ed13dee9931cd3a63c2027aec75fe3e44f976 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Mon, 27 May 2024 17:30:44 +0200 Subject: [PATCH 17/23] refactor: rename tokens to local / remote --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 53 ++++++++++--------- .../MultiAggregateRateLimiter.t.sol | 33 ++++++------ 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 3b06d26995..aa0bb3206d 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -30,16 +30,18 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, RateLimiter.Config config); event PriceRegistrySet(address newPriceRegistry); - event TokenAggregateRateLimitAdded(address sourceToken, address destToken); - event TokenAggregateRateLimitRemoved(address sourceToken, address destToken); + event TokenAggregateRateLimitAdded(address remoteToken, address localToken); + event TokenAggregateRateLimitRemoved(address remoteToken, address localToken); event AuthorizedCallerAdded(address caller); event AuthorizedCallerRemoved(address caller); /// @notice RateLimitToken struct containing both the source and destination token addresses struct RateLimitToken { - address sourceToken; - address destToken; + // TODO: change to bytes32 for non-EVM support + address remoteToken; + address localToken; } + // TODO: include chain selector in update /// @notice Update args for changing the authorized callers struct AuthorizedCallerArgs { @@ -53,8 +55,8 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { RateLimiter.Config rateLimiterConfig; // Rate limiter config to set } - /// @dev Tokens that should be included in Aggregate Rate Limiting (from dest -> source) - EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensDestToSource; + /// @dev Tokens that should be included in Aggregate Rate Limiting (from local chain (this chain) -> remote) + EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensLocalToRemote; /// @dev Set of callers that can call the validation functions (this is required since the validations modify state) EnumerableSet.AddressSet internal s_authorizedCallers; @@ -90,7 +92,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { uint256 value; Client.EVMTokenAmount[] memory destTokenAmounts = message.destTokenAmounts; for (uint256 i = 0; i < destTokenAmounts.length; ++i) { - if (s_rateLimitedTokensDestToSource.contains(destTokenAmounts[i].token)) { + if (s_rateLimitedTokensLocalToRemote.contains(destTokenAmounts[i].token)) { value += _getTokenValue(destTokenAmounts[i]); } } @@ -165,20 +167,21 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } /// @notice Get all tokens which are included in Aggregate Rate Limiting. - /// @return sourceTokens The source representation of the tokens that are rate limited. - /// @return destTokens The destination representation of the tokens that are rate limited. + /// @return remoteTokens The source representation of the tokens that are rate limited. + /// @return localTokens The destination representation of the tokens that are rate limited. /// @dev the order of IDs in the list is **not guaranteed**, therefore, if ordering matters when /// making successive calls, one should keep the blockheight constant to ensure a consistent result. - function getAllRateLimitTokens() external view returns (address[] memory sourceTokens, address[] memory destTokens) { - sourceTokens = new address[](s_rateLimitedTokensDestToSource.length()); - destTokens = new address[](s_rateLimitedTokensDestToSource.length()); - - for (uint256 i = 0; i < s_rateLimitedTokensDestToSource.length(); ++i) { - (address destToken, address sourceToken) = s_rateLimitedTokensDestToSource.at(i); - sourceTokens[i] = sourceToken; - destTokens[i] = destToken; + // TODO: include chain selector in request + function getAllRateLimitTokens() external view returns (address[] memory remoteTokens, address[] memory localTokens) { + remoteTokens = new address[](s_rateLimitedTokensLocalToRemote.length()); + localTokens = new address[](s_rateLimitedTokensLocalToRemote.length()); + + for (uint256 i = 0; i < s_rateLimitedTokensLocalToRemote.length(); ++i) { + (address localToken, address remoteToken) = s_rateLimitedTokensLocalToRemote.at(i); + remoteTokens[i] = remoteToken; + localTokens[i] = localToken; } - return (sourceTokens, destTokens); + return (remoteTokens, localTokens); } /// @notice Adds or removes tokens from being used in Aggregate Rate Limiting. @@ -186,21 +189,21 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @param adds - A list of one or more tokens to be added. function updateRateLimitTokens(RateLimitToken[] memory removes, RateLimitToken[] memory adds) external onlyOwner { for (uint256 i = 0; i < removes.length; ++i) { - if (s_rateLimitedTokensDestToSource.remove(removes[i].destToken)) { - emit TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); + if (s_rateLimitedTokensLocalToRemote.remove(removes[i].localToken)) { + emit TokenAggregateRateLimitRemoved(removes[i].remoteToken, removes[i].localToken); } } for (uint256 i = 0; i < adds.length; ++i) { - address destToken = adds[i].destToken; - address sourceToken = adds[i].sourceToken; + address localToken = adds[i].localToken; + address remoteToken = adds[i].remoteToken; - if (destToken == address(0) || sourceToken == address(0)) { + if (localToken == address(0) || remoteToken == address(0)) { revert ZeroAddressNotAllowed(); } - if (s_rateLimitedTokensDestToSource.set(destToken, sourceToken)) { - emit TokenAggregateRateLimitAdded(sourceToken, destToken); + if (s_rateLimitedTokensLocalToRemote.set(localToken, remoteToken)) { + emit TokenAggregateRateLimitAdded(remoteToken, localToken); } } } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 9206db6a59..204edfc51b 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -655,19 +655,20 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi MultiAggregateRateLimiter.RateLimitToken[] memory remove = new MultiAggregateRateLimiter.RateLimitToken[](s_sourceTokens.length); for (uint256 i = 0; i < s_sourceTokens.length; ++i) { - remove[i] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); + remove[i] = + MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_sourceTokens[i], localToken: s_destTokens[i]}); } s_rateLimiter.updateRateLimitTokens(remove, new MultiAggregateRateLimiter.RateLimitToken[](0)); } function test_UpdateRateLimitTokens_Success() public { MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](2); - adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); - adds[1] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_sourceTokens[0], localToken: s_destTokens[0]}); + adds[1] = MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_sourceTokens[1], localToken: s_destTokens[1]}); for (uint256 i = 0; i < adds.length; ++i) { vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].remoteToken, adds[i].localToken); } s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); @@ -675,29 +676,29 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi (address[] memory sourceTokens, address[] memory destTokens) = s_rateLimiter.getAllRateLimitTokens(); for (uint256 i = 0; i < adds.length; ++i) { - assertEq(adds[i].sourceToken, sourceTokens[i]); - assertEq(adds[i].destToken, destTokens[i]); + assertEq(adds[i].remoteToken, sourceTokens[i]); + assertEq(adds[i].localToken, destTokens[i]); } } function test_UpdateRateLimitTokens_AddsAndRemoves_Success() public { MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](2); - adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[0], destToken: s_destTokens[0]}); - adds[1] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_sourceTokens[0], localToken: s_destTokens[0]}); + adds[1] = MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_sourceTokens[1], localToken: s_destTokens[1]}); MultiAggregateRateLimiter.RateLimitToken[] memory removes = new MultiAggregateRateLimiter.RateLimitToken[](1); removes[0] = adds[0]; for (uint256 i = 0; i < adds.length; ++i) { vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].sourceToken, adds[i].destToken); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitAdded(adds[i].remoteToken, adds[i].localToken); } s_rateLimiter.updateRateLimitTokens(removes, adds); for (uint256 i = 0; i < removes.length; ++i) { vm.expectEmit(); - emit MultiAggregateRateLimiter.TokenAggregateRateLimitRemoved(removes[i].sourceToken, removes[i].destToken); + emit MultiAggregateRateLimiter.TokenAggregateRateLimitRemoved(removes[i].remoteToken, removes[i].localToken); } s_rateLimiter.updateRateLimitTokens(removes, new MultiAggregateRateLimiter.RateLimitToken[](0)); @@ -705,17 +706,17 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi (address[] memory sourceTokens, address[] memory destTokens) = s_rateLimiter.getAllRateLimitTokens(); assertEq(1, sourceTokens.length); - assertEq(adds[1].sourceToken, sourceTokens[0]); + assertEq(adds[1].remoteToken, sourceTokens[0]); assertEq(1, destTokens.length); - assertEq(adds[1].destToken, destTokens[0]); + assertEq(adds[1].localToken, destTokens[0]); } // Reverts function test_ZeroSourceToken_Revert() public { MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](1); - adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: address(0), destToken: s_destTokens[0]}); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({remoteToken: address(0), localToken: s_destTokens[0]}); vm.expectRevert(MultiAggregateRateLimiter.ZeroAddressNotAllowed.selector); s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); @@ -723,7 +724,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi function test_ZeroDestToken_Revert() public { MultiAggregateRateLimiter.RateLimitToken[] memory adds = new MultiAggregateRateLimiter.RateLimitToken[](1); - adds[0] = MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_destTokens[0], destToken: address(0)}); + adds[0] = MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_destTokens[0], localToken: address(0)}); vm.expectRevert(MultiAggregateRateLimiter.ZeroAddressNotAllowed.selector); s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.RateLimitToken[](0), adds); @@ -749,7 +750,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate new MultiAggregateRateLimiter.RateLimitToken[](s_sourceTokens.length); for (uint224 i = 0; i < s_sourceTokens.length; ++i) { tokensToAdd[i] = - MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[i], destToken: s_destTokens[i]}); + MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_sourceTokens[i], localToken: s_destTokens[i]}); Internal.PriceUpdates memory priceUpdates = getSingleTokenPriceUpdateStruct(s_destTokens[i], TOKEN_PRICE * (i + 1)); @@ -786,7 +787,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate function test_ValidateMessageWithDisabledRateLimitToken_Success() public { MultiAggregateRateLimiter.RateLimitToken[] memory tokensToRemove = new MultiAggregateRateLimiter.RateLimitToken[](1); tokensToRemove[0] = - MultiAggregateRateLimiter.RateLimitToken({sourceToken: s_sourceTokens[1], destToken: s_destTokens[1]}); + MultiAggregateRateLimiter.RateLimitToken({remoteToken: s_sourceTokens[1], localToken: s_destTokens[1]}); s_rateLimiter.updateRateLimitTokens(tokensToRemove, new MultiAggregateRateLimiter.RateLimitToken[](0)); Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](2); From 6add0097f79c5478729816394acf54b1bfc747b0 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Mon, 27 May 2024 18:33:37 +0200 Subject: [PATCH 18/23] feat: separate rate limits for incoming and outgoing lanes --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 63 ++++- .../MultiAggregateRateLimiterHelper.sol | 8 +- .../MultiAggregateRateLimiter.t.sol | 240 ++++++++++++++---- 3 files changed, 254 insertions(+), 57 deletions(-) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index aa0bb3206d..2edb6aba9c 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -28,7 +28,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { error ZeroAddressNotAllowed(); error ZeroChainSelectorNotAllowed(); - event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, RateLimiter.Config config); + event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, bool isOutgoingLane, RateLimiter.Config config); event PriceRegistrySet(address newPriceRegistry); event TokenAggregateRateLimitAdded(address remoteToken, address localToken); event TokenAggregateRateLimitRemoved(address remoteToken, address localToken); @@ -51,7 +51,8 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Update args for a single rate limiter config update struct RateLimiterConfigArgs { - uint64 remoteChainSelector; // Chain selector to set config for + uint64 remoteChainSelector; // ────╮ Chain selector to set config for + bool isOutgoingLane; // ───────────╯ If set to true, represents the outgoing message lane (OnRamp), and the incoming message lane otherwise (OffRamp) RateLimiter.Config rateLimiterConfig; // Rate limiter config to set } @@ -64,8 +65,13 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice The address of the PriceRegistry used to query token values for ratelimiting address internal s_priceRegistry; - /// @notice Rate limiter token bucket states per chain - mapping(uint64 remoteChainSelector => RateLimiter.TokenBucket rateLimiter) s_rateLimitersByChainSelector; + /// @notice Rate limiter token bucket states per chain. + /// For the key - the first 7 bits are discarded, the 8th bit represents the direction, the last 64 bits represent the chain selector. + /// Directions of 0 are used for the OffRamp (incoming messages), while directions are 1 are used for the OnRamp (outgoing messages) + mapping(uint72 remoteChainSelectorWithDirection => RateLimiter.TokenBucket rateLimiter) s_rateLimitersByChainSelector; + + /// @dev The direction in the remoteChainSelectorWithDirection key is in the 65th bit + uint72 internal DIRECTION_BIT_MASK = 1 << 64; /// @param rateLimiterConfigs The RateLimiter.Configs per chain containing the capacity and refill rate /// of the bucket @@ -97,7 +103,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } } - if (value > 0) _rateLimitValue(message.sourceChainSelector, value); + if (value > 0) _rateLimitValue(message.sourceChainSelector, false, value); } /// @inheritdoc IMessageValidator @@ -105,11 +111,35 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { // TODO: to be implemented (assuming the same rate limiter states are shared for incoming and outgoing messages) } + /// @notice Returns the remoteChainWithDirection key value that can be used to get the correct lane selector. + /// @param remoteChainSelector Remote chain selector to fetch key for + /// @param isOutgoingLane if set to true, fetches the rate limit for the outgoing message lane (OnRamp). Otherwise fetches for the incoming message lane (OffRamp). + /// The outgoing and incoming message rate limit state is completely separated. + /// @return remoteChainSelectorWithDirection Remote chain selector with direction key + /// (2^64) | remoteChainSelector if isOutgoingLane is set to true, and the unmodified remoteChainSelector otherwise + function _getChainSelectorWithDirection( + uint64 remoteChainSelector, + bool isOutgoingLane + ) internal view returns (uint72) { + uint72 remoteChainWithDirection = remoteChainSelector; + + // Flip the direction bit + if (isOutgoingLane) { + remoteChainWithDirection |= DIRECTION_BIT_MASK; + } + + return remoteChainWithDirection; + } + /// @notice Consumes value from the rate limiter bucket based on the token value given. /// @param remoteChainSelector chain selector to apply rate limit to + /// @param isOutgoingLane if set to true, fetches the rate limit for the outgoing message lane (OnRamp). Otherwise fetches for the incoming message lane (OffRamp). + /// The outgoing and incoming message rate limit state is completely separated. /// @param value consumed value - function _rateLimitValue(uint64 remoteChainSelector, uint256 value) internal { - s_rateLimitersByChainSelector[remoteChainSelector]._consume(value, address(0)); + function _rateLimitValue(uint64 remoteChainSelector, bool isOutgoingLane, uint256 value) internal { + s_rateLimitersByChainSelector[_getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane)]._consume( + value, address(0) + ); } /// @notice Retrieves the token value for a token using the PriceRegistry @@ -124,9 +154,15 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { /// @notice Gets the token bucket with its values for the block it was requested at. /// @param remoteChainSelector chain selector to retrieve state for + /// @param isOutgoingLane if set to true, fetches the rate limit for the outgoing message lane (OnRamp). Otherwise fetches for the incoming message lane (OffRamp). + /// The outgoing and incoming message rate limit state is completely separated. /// @return The token bucket. - function currentRateLimiterState(uint64 remoteChainSelector) external view returns (RateLimiter.TokenBucket memory) { - return s_rateLimitersByChainSelector[remoteChainSelector]._currentTokenBucketState(); + function currentRateLimiterState( + uint64 remoteChainSelector, + bool isOutgoingLane + ) external view returns (RateLimiter.TokenBucket memory) { + return s_rateLimitersByChainSelector[_getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane)] + ._currentTokenBucketState(); } /// @notice Applies the provided rate limiter config updates. @@ -148,11 +184,14 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { revert ZeroChainSelectorNotAllowed(); } - RateLimiter.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[remoteChainSelector]; + bool isOutgoingLane = updateArgs.isOutgoingLane; + uint72 remoteChainSelectorWithDirection = _getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane); + + RateLimiter.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[remoteChainSelectorWithDirection]; if (tokenBucket.lastUpdated == 0) { // Token bucket needs to be newly added - s_rateLimitersByChainSelector[remoteChainSelector] = RateLimiter.TokenBucket({ + s_rateLimitersByChainSelector[remoteChainSelectorWithDirection] = RateLimiter.TokenBucket({ rate: configUpdate.rate, capacity: configUpdate.capacity, tokens: configUpdate.capacity, @@ -162,7 +201,7 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { } else { tokenBucket._setTokenBucketConfig(configUpdate); } - emit RateLimiterConfigUpdated(remoteChainSelector, configUpdate); + emit RateLimiterConfigUpdated(remoteChainSelector, isOutgoingLane, configUpdate); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index 1e684d5ef0..ba0ddac2e2 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -12,11 +12,15 @@ contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { address[] memory authorizedCallers ) MultiAggregateRateLimiter(rateLimiterConfigs, priceRegistry, authorizedCallers) {} - function rateLimitValue(uint64 chainSelector, uint256 value) public { - _rateLimitValue(chainSelector, value); + function rateLimitValue(uint64 chainSelector, bool isOutgoingLane, uint256 value) public { + _rateLimitValue(chainSelector, isOutgoingLane, value); } function getTokenValue(Client.EVMTokenAmount memory tokenAmount) public view returns (uint256) { return _getTokenValue(tokenAmount); } + + function getChainSelectorWithDirection(uint64 remoteChainSelector, bool isOutgoingLane) public view returns (uint72) { + return _getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane); + } } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 204edfc51b..cc256dcbbe 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -38,13 +38,20 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { s_priceRegistry.updatePrices(priceUpdates); MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](3); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_2, + isOutgoingLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); + configUpdates[2] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: true, rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); @@ -113,13 +120,20 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup function test_Constructor_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](3); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); configUpdates[1] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_2, + isOutgoingLane: false, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); + configUpdates[2] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: true, rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); @@ -128,10 +142,13 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup authorizedCallers[1] = MOCK_ONRAMP; vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated(CHAIN_SELECTOR_1, RATE_LIMITER_CONFIG_1); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated(CHAIN_SELECTOR_1, false, RATE_LIMITER_CONFIG_1); vm.expectEmit(); - emit MultiAggregateRateLimiter.RateLimiterConfigUpdated(CHAIN_SELECTOR_2, RATE_LIMITER_CONFIG_2); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated(CHAIN_SELECTOR_2, false, RATE_LIMITER_CONFIG_2); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated(CHAIN_SELECTOR_1, true, RATE_LIMITER_CONFIG_2); vm.expectEmit(); emit MultiAggregateRateLimiter.PriceRegistrySet(address(s_priceRegistry)); @@ -147,13 +164,36 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup assertEq(OWNER, s_rateLimiter.owner()); assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); - RateLimiter.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucketSrcChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketSrcChain1); assertEq(BLOCK_TIME, bucketSrcChain1.lastUpdated); - RateLimiter.TokenBucket memory bucketSrcChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + RateLimiter.TokenBucket memory bucketSrcChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_2, bucketSrcChain2); assertEq(BLOCK_TIME, bucketSrcChain2.lastUpdated); + + RateLimiter.TokenBucket memory bucketSrcChainOutgoing = + s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_2, bucketSrcChainOutgoing); + assertEq(BLOCK_TIME, bucketSrcChainOutgoing.lastUpdated); + } +} + +contract MultiAggregateRateLimiter_getChainSelectorWithDirection is MultiAggregateRateLimiterSetup { + function test_IncomingLane_Fuzz_Success(uint64 remoteChainSelector) public view { + uint72 remoteChainSelectorWithDirection = s_rateLimiter.getChainSelectorWithDirection(remoteChainSelector, true); + + // 1 << 64 | remoteChainSelector should be equivalent to ((2^64) + remoteChianSelector) + uint72 expectedRemoteChainSelector = uint72(type(uint64).max) + 1 + remoteChainSelector; + assertEq(remoteChainSelectorWithDirection, expectedRemoteChainSelector); + + // Should never clash with the remoteChainSelector + assertNotEq(remoteChainSelectorWithDirection, remoteChainSelector); + } + + function test_OutgoingLane_Fuzz_Success(uint64 remoteChainSelector) public view { + uint72 remoteChainSelectorWithDirection = s_rateLimiter.getChainSelectorWithDirection(remoteChainSelector, false); + assertEq(remoteChainSelectorWithDirection, remoteChainSelector); } } @@ -331,11 +371,13 @@ contract MultiAggregateRateLimiter_setAuthorizedCallers is MultiAggregateRateLim contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSetup { function test_GetTokenBucket_Success() public view { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); - assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); - assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); - assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.tokens); - assertEq(BLOCK_TIME, bucket.lastUpdated); + RateLimiter.TokenBucket memory bucketIncoming = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_1, bucketIncoming); + assertEq(BLOCK_TIME, bucketIncoming.lastUpdated); + + RateLimiter.TokenBucket memory bucketOutgoing = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + _assertConfigWithTokenBucketEquality(RATE_LIMITER_CONFIG_2, bucketOutgoing); + assertEq(BLOCK_TIME, bucketOutgoing.lastUpdated); } function test_Refill_Success() public { @@ -345,12 +387,13 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); @@ -360,7 +403,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe uint256 warpTime = 4; vm.warp(BLOCK_TIME + warpTime); - bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); assertEq(RATE_LIMITER_CONFIG_1.rate, bucket.rate); assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.capacity); @@ -370,7 +413,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe vm.warp(BLOCK_TIME + warpTime * 100); // Bucket overflow - bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); assertEq(RATE_LIMITER_CONFIG_1.capacity, bucket.tokens); } @@ -380,7 +423,7 @@ contract MultiAggregateRateLimiter_getTokenBucket is MultiAggregateRateLimiterSe vm.warp(BLOCK_TIME - 1); vm.expectRevert(stdError.arithmeticError); - s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); } } @@ -401,12 +444,13 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig + configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig ); vm.recordLogs(); @@ -415,24 +459,83 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega Vm.Log[] memory logEntries = vm.getRecordedLogs(); assertEq(logEntries.length, 1); - RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); + RateLimiter.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); + _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); + assertEq(BLOCK_TIME, bucket1.lastUpdated); + } + + function test_SingleConfigOutgoing_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); + configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutgoingLane: true, + rateLimiterConfig: RATE_LIMITER_CONFIG_2 + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[0].remoteChainSelector, true, configUpdates[0].rateLimiterConfig + ); + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, 1); + + RateLimiter.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, true); _assertConfigWithTokenBucketEquality(configUpdates[0].rateLimiterConfig, bucket1); assertEq(BLOCK_TIME, bucket1.lastUpdated); } function test_MultipleConfigs_Success() public { MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = - new MultiAggregateRateLimiter.RateLimiterConfigArgs[](3); + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](5); for (uint64 i; i < configUpdates.length; ++i) { configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1 + i + 1, + isOutgoingLane: i % 2 == 0 ? false : true, + rateLimiterConfig: RateLimiter.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) + }); + + vm.expectEmit(); + emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( + configUpdates[i].remoteChainSelector, configUpdates[i].isOutgoingLane, configUpdates[i].rateLimiterConfig + ); + } + + vm.recordLogs(); + s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); + + Vm.Log[] memory logEntries = vm.getRecordedLogs(); + assertEq(logEntries.length, configUpdates.length); + + for (uint256 i; i < configUpdates.length; ++i) { + RateLimiter.TokenBucket memory bucket = + s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector, configUpdates[i].isOutgoingLane); + _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); + assertEq(BLOCK_TIME, bucket.lastUpdated); + } + } + + function test_MultipleConfigsBothLanes_Success() public { + MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = + new MultiAggregateRateLimiter.RateLimiterConfigArgs[](2); + + for (uint64 i; i < configUpdates.length; ++i) { + configUpdates[i] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ + remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutgoingLane: i % 2 == 0 ? false : true, rateLimiterConfig: RateLimiter.Config({isEnabled: true, rate: 5 + i, capacity: 100 + i}) }); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[i].remoteChainSelector, configUpdates[i].rateLimiterConfig + configUpdates[i].remoteChainSelector, configUpdates[i].isOutgoingLane, configUpdates[i].rateLimiterConfig ); } @@ -444,7 +547,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega for (uint256 i; i < configUpdates.length; ++i) { RateLimiter.TokenBucket memory bucket = - s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[i].remoteChainSelector, configUpdates[i].isOutgoingLane); _assertConfigWithTokenBucketEquality(configUpdates[i].rateLimiterConfig, bucket); assertEq(BLOCK_TIME, bucket.lastUpdated); } @@ -455,28 +558,35 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_2 }); - RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); + RateLimiter.TokenBucket memory bucket1 = + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); // Capacity equals tokens assertEq(bucket1.capacity, bucket1.tokens); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig + configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig ); vm.recordLogs(); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); vm.warp(BLOCK_TIME + 1); - bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); + bucket1 = s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); assertEq(BLOCK_TIME + 1, bucket1.lastUpdated); // Tokens < capacity since capacity doubled assertTrue(bucket1.capacity != bucket1.tokens); + + // Outgoing lane config remains unchanged + _assertConfigWithTokenBucketEquality( + RATE_LIMITER_CONFIG_2, s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true) + ); } function test_UpdateExistingConfigWithNoDifference_Success() public { @@ -484,15 +594,16 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); RateLimiter.TokenBucket memory bucketPreUpdate = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); vm.expectEmit(); emit MultiAggregateRateLimiter.RateLimiterConfigUpdated( - configUpdates[0].remoteChainSelector, configUpdates[0].rateLimiterConfig + configUpdates[0].remoteChainSelector, false, configUpdates[0].rateLimiterConfig ); vm.recordLogs(); @@ -500,7 +611,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega vm.warp(BLOCK_TIME + 1); RateLimiter.TokenBucket memory bucketPostUpdate = - s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector); + s_rateLimiter.currentRateLimiterState(configUpdates[0].remoteChainSelector, false); _assertTokenBucketEquality(bucketPreUpdate, bucketPostUpdate); assertEq(BLOCK_TIME + 1, bucketPostUpdate.lastUpdated); } @@ -511,6 +622,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: 0, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); @@ -523,6 +635,7 @@ contract MultiAggregateRateLimiter_applyRateLimiterConfigUpdates is MultiAggrega new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1 + 1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); vm.startPrank(STRANGER); @@ -546,11 +659,11 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS emit RateLimiter.TokensConsumed(value); vm.resumeGasMetering(); - s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, false, value); vm.pauseGasMetering(); // Get the updated bucket status - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); // Assert the proper value has been taken out of the bucket assertEq(bucket.capacity - value, bucket.tokens); @@ -560,14 +673,14 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS vm.expectRevert( abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, waitTime, bucket.tokens) ); - s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, false, value); // Move the block time forward by 10 so the bucket refills by 10 * rate vm.warp(BLOCK_TIME + 1 + waitTime); // The bucket has filled up enough so we can take out more tokens - s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); - bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, false, value); + bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); assertEq(bucket.capacity - value + waitTime * RATE_LIMITER_CONFIG_1.rate - value, bucket.tokens); vm.resumeGasMetering(); } @@ -585,12 +698,12 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS emit RateLimiter.TokensConsumed(value); vm.resumeGasMetering(); - s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, false, value); vm.pauseGasMetering(); // Get the updated bucket status - RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); - RateLimiter.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + RateLimiter.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); // Assert the proper value has been taken out of the bucket assertEq(bucket1.capacity - value, bucket1.tokens); @@ -601,21 +714,61 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS emit RateLimiter.TokensConsumed(value); vm.resumeGasMetering(); - s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_2, value); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_2, false, value); vm.pauseGasMetering(); - bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); - bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); assertEq(bucket2.capacity - value, bucket2.tokens); // CHAIN_SELECTOR_1 should remain unchanged assertEq(bucket1.capacity - value, bucket1.tokens); } + function test_RateLimitValueDifferentLanes_Success() public { + vm.pauseGasMetering(); + // start from blocktime that does not equal rate limiter init timestamp + vm.warp(BLOCK_TIME + 1); + + // 15 (tokens) * 4 (price) * 2 (number of times) > 100 (capacity) + uint256 numberOfTokens = 15; + uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(value); + + vm.resumeGasMetering(); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, false, value); + vm.pauseGasMetering(); + + // Get the updated bucket status + RateLimiter.TokenBucket memory bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + RateLimiter.TokenBucket memory bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + + // Assert the proper value has been taken out of the bucket + assertEq(bucket1.capacity - value, bucket1.tokens); + // Outgoing lane should remain unchanged + assertEq(bucket2.capacity, bucket2.tokens); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(value); + + vm.resumeGasMetering(); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, true, value); + vm.pauseGasMetering(); + + bucket1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); + bucket2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, true); + + assertEq(bucket2.capacity - value, bucket2.tokens); + // Incoming lane should remain unchanged + assertEq(bucket1.capacity - value, bucket1.tokens); + } + // Reverts function test_AggregateValueMaxCapacityExceeded_Revert() public { - RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucket = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); uint256 numberOfTokens = 100; uint256 value = (numberOfTokens * TOKEN_PRICE) / 1e18; @@ -625,7 +778,7 @@ contract MultiAggregateRateLimiter__rateLimitValue is MultiAggregateRateLimiterS RateLimiter.AggregateValueMaxCapacityExceeded.selector, bucket.capacity, (numberOfTokens * TOKEN_PRICE) / 1e18 ) ); - s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, value); + s_rateLimiter.rateLimitValue(CHAIN_SELECTOR_1, false, value); } } @@ -807,6 +960,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate new MultiAggregateRateLimiter.RateLimiterConfigArgs[](1); configUpdates[0] = MultiAggregateRateLimiter.RateLimiterConfigArgs({ remoteChainSelector: CHAIN_SELECTOR_1, + isOutgoingLane: false, rateLimiterConfig: RATE_LIMITER_CONFIG_1 }); configUpdates[0].rateLimiterConfig.isEnabled = false; @@ -838,11 +992,11 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Chain 1 changed - RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); // Chain 2 unchanged - RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + RateLimiter.TokenBucket memory bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); assertEq(bucketChain2.capacity, bucketChain2.tokens); vm.expectEmit(); @@ -851,11 +1005,11 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); // Chain 1 unchanged - bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1); + bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); assertEq(bucketChain1.capacity - totalValue, bucketChain1.tokens); // Chain 2 changed - bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2); + bucketChain2 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_2, false); assertEq(bucketChain2.capacity - totalValue, bucketChain2.tokens); } From ba202a7cc5dc260b911f0dd97a1a40c10f7ce1bc Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Tue, 28 May 2024 11:43:44 +0200 Subject: [PATCH 19/23] refactor: rename validator to IMessageInterceptor --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 12 ++++----- .../ccip/interfaces/IMessageInterceptor.sol | 22 ++++++++++++++++ .../ccip/interfaces/IMessageValidator.sol | 22 ---------------- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 8 +++--- ...elper.sol => MessageInterceptorHelper.sol} | 12 ++++----- .../test/offRamp/EVM2EVMMultiOffRamp.t.sol | 22 ++++++++++------ .../offRamp/EVM2EVMMultiOffRampSetup.t.sol | 6 ++--- .../MultiAggregateRateLimiter.t.sol | 26 +++++++++---------- 8 files changed, 68 insertions(+), 62 deletions(-) create mode 100644 contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol delete mode 100644 contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol rename contracts/src/v0.8/ccip/test/helpers/{MessageValidatorHelper.sol => MessageInterceptorHelper.sol} (60%) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 2edb6aba9c..1ba6791c19 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IMessageValidator} from "./interfaces/IMessageValidator.sol"; +import {IMessageInterceptor} from "./interfaces/IMessageInterceptor.sol"; import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; @@ -16,7 +16,7 @@ import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; /// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). /// The contract is a standalone multi-lane message validator contract, which can be called by authorized /// ramp contracts to apply rate limit changes to lanes, and revert when the rate limits get breached. -contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { +contract MultiAggregateRateLimiter is IMessageInterceptor, OwnerIsCreator { using RateLimiter for RateLimiter.TokenBucket; using USDPriceWith18Decimals for uint224; using EnumerableMapAddresses for EnumerableMapAddresses.AddressToAddressMap; @@ -89,8 +89,8 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { ); } - /// @inheritdoc IMessageValidator - function validateIncomingMessage(Client.Any2EVMMessage memory message) external { + /// @inheritdoc IMessageInterceptor + function onIncomingMessage(Client.Any2EVMMessage memory message) external { if (!s_authorizedCallers.contains(msg.sender)) { revert UnauthorizedCaller(msg.sender); } @@ -106,8 +106,8 @@ contract MultiAggregateRateLimiter is IMessageValidator, OwnerIsCreator { if (value > 0) _rateLimitValue(message.sourceChainSelector, false, value); } - /// @inheritdoc IMessageValidator - function validateOutgoingMessage(Client.EVM2AnyMessage memory message, uint64 destChainSelector) external { + /// @inheritdoc IMessageInterceptor + function onOutgoingMessage(Client.EVM2AnyMessage memory message, uint64 destChainSelector) external { // TODO: to be implemented (assuming the same rate limiter states are shared for incoming and outgoing messages) } diff --git a/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol b/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol new file mode 100644 index 0000000000..cacc276fe0 --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/IMessageInterceptor.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Client} from "../libraries/Client.sol"; + +/// @notice Interface for plug-in message hook contracts that intercept OffRamp & OnRamp messages +/// and perform validations / state changes on top of the messages. The interceptor functions are expected to +/// revert on validation failures. +interface IMessageInterceptor { + /// @notice Common error that can be thrown on validation failures and used by consumers + /// @param errorReason abi encoded revert reason + error MessageValidationError(bytes errorReason); + + /// @notice Intercepts & validates the given OffRamp message. Reverts on validation failure + /// @param message to validate + function onIncomingMessage(Client.Any2EVMMessage memory message) external; + + /// @notice Intercepts & validates the given OnRamp message. Reverts on validation failure + /// @param message to validate + /// @param destChainSelector remote destination chain selector where the message is being sent to + function onOutgoingMessage(Client.EVM2AnyMessage memory message, uint64 destChainSelector) external; +} diff --git a/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol b/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol deleted file mode 100644 index ff30c27f3c..0000000000 --- a/contracts/src/v0.8/ccip/interfaces/IMessageValidator.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {Client} from "../libraries/Client.sol"; - -/// @notice Interface for plug-in message validator contracts that intercept OffRamp & OnRamp messages -/// and perform validations on top of the messages. All validation functions are expected to -/// revert on validation failures. -interface IMessageValidator { - /// @notice Common error that can be thrown on validation failures and used by consumers - /// @param errorReason abi encoded revert reason - error MessageValidationError(bytes errorReason); - - /// @notice Validates the given OffRamp message. Reverts on validation failure - /// @param message to validate - function validateIncomingMessage(Client.Any2EVMMessage memory message) external; - - /// @notice Validates the given OnRamp message. Reverts on validation failure - /// @param message to valdidate - /// @param destChainSelector dest chain selector where the message is being sent to - function validateOutgoingMessage(Client.EVM2AnyMessage memory message, uint64 destChainSelector) external; -} diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index b076b14033..d7d088bb16 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -5,7 +5,7 @@ import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; import {IAny2EVMMultiOffRamp} from "../interfaces/IAny2EVMMultiOffRamp.sol"; import {IAny2EVMOffRamp} from "../interfaces/IAny2EVMOffRamp.sol"; -import {IMessageValidator} from "../interfaces/IMessageValidator.sol"; +import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; import {IMultiCommitStore} from "../interfaces/IMultiCommitStore.sol"; import {IPool} from "../interfaces/IPool.sol"; import {IRMN} from "../interfaces/IRMN.sol"; @@ -499,7 +499,7 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN ReceiverError.selector == errorSelector || TokenHandlingError.selector == errorSelector || Internal.InvalidEVMAddress.selector == errorSelector || InvalidDataLength.selector == errorSelector || CallWithExactGas.NoContract.selector == errorSelector || NotACompatiblePool.selector == errorSelector - || IMessageValidator.MessageValidationError.selector == errorSelector + || IMessageInterceptor.MessageValidationError.selector == errorSelector ) { // If CCIP receiver execution is not successful, bubble up receiver revert data, // prepended by the 4 bytes of ReceiverError.selector, TokenHandlingError.selector or InvalidPoolAddress.selector. @@ -554,9 +554,9 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN address messageValidator = s_dynamicConfig.messageValidator; if (messageValidator != address(0)) { - try IMessageValidator(messageValidator).validateIncomingMessage(any2EvmMessage) {} + try IMessageInterceptor(messageValidator).onIncomingMessage(any2EvmMessage) {} catch (bytes memory err) { - revert IMessageValidator.MessageValidationError(err); + revert IMessageInterceptor.MessageValidationError(err); } } diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol similarity index 60% rename from contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol rename to contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol index 15a0bec7cc..e6ea39c505 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageValidatorHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import "../../interfaces/IMessageValidator.sol"; +import "../../interfaces/IMessageInterceptor.sol"; -contract MessageValidatorHelper is IMessageValidator { +contract MessageInterceptorHelper is IMessageInterceptor { error IncomingMessageValidationError(bytes errorReason); mapping(bytes32 messageId => bool isInvalid) internal s_invalidMessageIds; @@ -14,15 +14,15 @@ contract MessageValidatorHelper is IMessageValidator { s_invalidMessageIds[messageId] = isInvalid; } - /// @inheritdoc IMessageValidator - function validateIncomingMessage(Client.Any2EVMMessage memory message) external view { + /// @inheritdoc IMessageInterceptor + function onIncomingMessage(Client.Any2EVMMessage memory message) external view { if (s_invalidMessageIds[message.messageId]) { revert IncomingMessageValidationError(bytes("Invalid message")); } } - /// @inheritdoc IMessageValidator - function validateOutgoingMessage(Client.EVM2AnyMessage memory, uint64) external pure { + /// @inheritdoc IMessageInterceptor + function onOutgoingMessage(Client.EVM2AnyMessage memory, uint64) external pure { // TODO: to be implemented return; } diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index 5d585c0046..93f0887384 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -8,7 +8,7 @@ import {IPool} from "../../interfaces/IPool.sol"; import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; import {RMN} from "../../RMN.sol"; import {Router} from "../../Router.sol"; -import {IMessageValidator} from "../../interfaces/IMessageValidator.sol"; +import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {Pool} from "../../libraries/Pool.sol"; @@ -19,7 +19,7 @@ import {TokenPool} from "../../pools/TokenPool.sol"; import {EVM2EVMMultiOffRampHelper} from "../helpers/EVM2EVMMultiOffRampHelper.sol"; import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {MessageValidatorHelper} from "../helpers/MessageValidatorHelper.sol"; +import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; import {ConformingReceiver} from "../helpers/receivers/ConformingReceiver.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {MaybeRevertMessageReceiverNo165} from "../helpers/receivers/MaybeRevertMessageReceiverNo165.sol"; @@ -1224,8 +1224,10 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { s_messageValidator.setMessageIdValidationState(message.messageId, true); vm.expectRevert( abi.encodeWithSelector( - IMessageValidator.MessageValidationError.selector, - abi.encodeWithSelector(MessageValidatorHelper.IncomingMessageValidationError.selector, bytes("Invalid message")) + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector( + MessageInterceptorHelper.IncomingMessageValidationError.selector, bytes("Invalid message") + ) ) ); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); @@ -1951,8 +1953,10 @@ contract EVM2EVMMultiOffRamp_report is EVM2EVMMultiOffRampSetup { messages1[0].messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( - IMessageValidator.MessageValidationError.selector, - abi.encodeWithSelector(MessageValidatorHelper.IncomingMessageValidationError.selector, bytes("Invalid message")) + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector( + MessageInterceptorHelper.IncomingMessageValidationError.selector, bytes("Invalid message") + ) ) ); @@ -1972,8 +1976,10 @@ contract EVM2EVMMultiOffRamp_report is EVM2EVMMultiOffRampSetup { messages2[0].messageId, Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( - IMessageValidator.MessageValidationError.selector, - abi.encodeWithSelector(MessageValidatorHelper.IncomingMessageValidationError.selector, bytes("Invalid message")) + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector( + MessageInterceptorHelper.IncomingMessageValidationError.selector, bytes("Invalid message") + ) ) ); diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol index bef9bbeddb..bc29899399 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRampSetup.t.sol @@ -18,7 +18,7 @@ import {EVM2EVMMultiOffRampHelper} from "../helpers/EVM2EVMMultiOffRampHelper.so import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; -import {MessageValidatorHelper} from "../helpers/MessageValidatorHelper.sol"; +import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {MockCommitStore} from "../mocks/MockCommitStore.sol"; import {MockMultiCommitStore} from "../mocks/MockMultiCommitStore.sol"; @@ -44,7 +44,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet MaybeRevertingBurnMintTokenPool internal s_maybeRevertingPool; EVM2EVMMultiOffRampHelper internal s_offRamp; - MessageValidatorHelper internal s_messageValidator; + MessageInterceptorHelper internal s_messageValidator; address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); event ExecutionStateChanged( @@ -60,7 +60,7 @@ contract EVM2EVMMultiOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSet PriceRegistrySetup.setUp(); OCR2BaseSetup.setUp(); - s_messageValidator = new MessageValidatorHelper(); + s_messageValidator = new MessageInterceptorHelper(); s_mockCommitStore = new MockMultiCommitStore(); s_receiver = new MaybeRevertMessageReceiver(false); s_secondary_receiver = new MaybeRevertMessageReceiver(false); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index cc256dcbbe..075ff29992 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -893,7 +893,7 @@ contract MultiAggregateRateLimiter_updateRateLimitTokens is MultiAggregateRateLi } } -contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRateLimiterSetup { +contract MultiAggregateRateLimiter_onIncomingMessage is MultiAggregateRateLimiterSetup { address internal immutable MOCK_RECEIVER = address(1113); function setUp() public virtual override { @@ -916,7 +916,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate vm.startPrank(MOCK_OFFRAMP); vm.recordLogs(); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); // No consumed rate limit events Vm.Log[] memory logEntries = vm.getRecordedLogs(); @@ -934,7 +934,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate vm.expectEmit(); emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } function test_ValidateMessageWithDisabledRateLimitToken_Success() public { @@ -952,7 +952,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate vm.expectEmit(); emit RateLimiter.TokensConsumed((5 * TOKEN_PRICE) / 1e18); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } function test_ValidateMessageWithRateLimitDisabled_Success() public { @@ -972,7 +972,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate tokenAmounts[1] = Client.EVMTokenAmount({token: s_destTokens[1], amount: 50}); vm.startPrank(MOCK_OFFRAMP); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // No consumed rate limit events Vm.Log[] memory logEntries = vm.getRecordedLogs(); @@ -989,7 +989,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate // 2 tokens * (TOKEN_PRICE) + 1 token * (2 * TOKEN_PRICE) uint256 totalValue = (4 * TOKEN_PRICE) / 1e18; - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Chain 1 changed RateLimiter.TokenBucket memory bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); @@ -1002,7 +1002,7 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate vm.expectEmit(); emit RateLimiter.TokensConsumed((4 * TOKEN_PRICE) / 1e18); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_2, tokenAmounts)); // Chain 1 unchanged bucketChain1 = s_rateLimiter.currentRateLimiterState(CHAIN_SELECTOR_1, false); @@ -1020,20 +1020,20 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate tokenAmounts[0] = Client.EVMTokenAmount({token: s_destTokens[0], amount: 20}); // Remaining capacity: 100 -> 20 - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Cannot fit 80 rate limit value (need to wait at least 12 blocks, current capacity is 20) vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 12, 20)); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Remaining capacity: 20 -> 35 (need to wait 9 more blocks) vm.warp(BLOCK_TIME + 3); vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueRateLimitReached.selector, 9, 35)); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); // Remaining capacity: 35 -> 80 (can fit exactly 80) vm.warp(BLOCK_TIME + 12); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } // Reverts @@ -1047,14 +1047,14 @@ contract MultiAggregateRateLimiter_validateIncomingMessage is MultiAggregateRate uint256 totalValue = (80 * TOKEN_PRICE + 2 * (30 * TOKEN_PRICE)) / 1e18; vm.expectRevert(abi.encodeWithSelector(RateLimiter.AggregateValueMaxCapacityExceeded.selector, 100, totalValue)); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessage(CHAIN_SELECTOR_1, tokenAmounts)); } function test_ValidateMessageFromUnauthorizedCaller_Revert() public { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(MultiAggregateRateLimiter.UnauthorizedCaller.selector, STRANGER)); - s_rateLimiter.validateIncomingMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); + s_rateLimiter.onIncomingMessage(_generateAny2EVMMessageNoTokens(CHAIN_SELECTOR_1)); } function _generateAny2EVMMessageNoTokens(uint64 sourceChainSelector) From 27efcd7e9e02a5e4fca8c63839fa036cfea75a03 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Tue, 28 May 2024 11:59:56 +0200 Subject: [PATCH 20/23] refactor: replace bit manipulation approach with structs for lane state separation --- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 64 +++++++++---------- .../MultiAggregateRateLimiterHelper.sol | 4 -- .../MultiAggregateRateLimiter.t.sol | 18 ------ 3 files changed, 32 insertions(+), 54 deletions(-) diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 1ba6791c19..17ce739247 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -56,6 +56,12 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, OwnerIsCreator { RateLimiter.Config rateLimiterConfig; // Rate limiter config to set } + /// @notice Struct to store rate limit token buckets for both lane directions + struct RateLimiterBuckets { + RateLimiter.TokenBucket incomingLaneBucket; // Bucket for the incoming lane (remote -> local) + RateLimiter.TokenBucket outgoingLaneBucket; // Bucket for the outgoing lane (local -> remote) + } + /// @dev Tokens that should be included in Aggregate Rate Limiting (from local chain (this chain) -> remote) EnumerableMapAddresses.AddressToAddressMap internal s_rateLimitedTokensLocalToRemote; @@ -65,13 +71,8 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, OwnerIsCreator { /// @notice The address of the PriceRegistry used to query token values for ratelimiting address internal s_priceRegistry; - /// @notice Rate limiter token bucket states per chain. - /// For the key - the first 7 bits are discarded, the 8th bit represents the direction, the last 64 bits represent the chain selector. - /// Directions of 0 are used for the OffRamp (incoming messages), while directions are 1 are used for the OnRamp (outgoing messages) - mapping(uint72 remoteChainSelectorWithDirection => RateLimiter.TokenBucket rateLimiter) s_rateLimitersByChainSelector; - - /// @dev The direction in the remoteChainSelectorWithDirection key is in the 65th bit - uint72 internal DIRECTION_BIT_MASK = 1 << 64; + /// @notice Rate limiter token bucket states per chain, with separate buckets for incoming and outgoing lanes. + mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) s_rateLimitersByChainSelector; /// @param rateLimiterConfigs The RateLimiter.Configs per chain containing the capacity and refill rate /// of the bucket @@ -111,35 +112,29 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, OwnerIsCreator { // TODO: to be implemented (assuming the same rate limiter states are shared for incoming and outgoing messages) } - /// @notice Returns the remoteChainWithDirection key value that can be used to get the correct lane selector. - /// @param remoteChainSelector Remote chain selector to fetch key for - /// @param isOutgoingLane if set to true, fetches the rate limit for the outgoing message lane (OnRamp). Otherwise fetches for the incoming message lane (OffRamp). - /// The outgoing and incoming message rate limit state is completely separated. - /// @return remoteChainSelectorWithDirection Remote chain selector with direction key - /// (2^64) | remoteChainSelector if isOutgoingLane is set to true, and the unmodified remoteChainSelector otherwise - function _getChainSelectorWithDirection( + /// @param remoteChainSelector chain selector to retrieve token bucket for + /// @param isOutgoingLane if set to true, fetches the bucket for the outgoing message lane (OnRamp). + /// Otherwise fetches for the incoming message lane (OffRamp). + /// @return bucket Storage pointer to the token bucket representing a specific lane + function _getTokenBucket( uint64 remoteChainSelector, bool isOutgoingLane - ) internal view returns (uint72) { - uint72 remoteChainWithDirection = remoteChainSelector; - - // Flip the direction bit + ) internal view returns (RateLimiter.TokenBucket storage) { + RateLimiterBuckets storage rateLimiterBuckets = s_rateLimitersByChainSelector[remoteChainSelector]; if (isOutgoingLane) { - remoteChainWithDirection |= DIRECTION_BIT_MASK; + return rateLimiterBuckets.outgoingLaneBucket; + } else { + return rateLimiterBuckets.incomingLaneBucket; } - - return remoteChainWithDirection; } /// @notice Consumes value from the rate limiter bucket based on the token value given. /// @param remoteChainSelector chain selector to apply rate limit to - /// @param isOutgoingLane if set to true, fetches the rate limit for the outgoing message lane (OnRamp). Otherwise fetches for the incoming message lane (OffRamp). - /// The outgoing and incoming message rate limit state is completely separated. + /// @param isOutgoingLane if set to true, applies the rate limit for the outgoing message lane (OnRamp). + /// Otherwise fetches for the incoming message lane (OffRamp). /// @param value consumed value function _rateLimitValue(uint64 remoteChainSelector, bool isOutgoingLane, uint256 value) internal { - s_rateLimitersByChainSelector[_getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane)]._consume( - value, address(0) - ); + _getTokenBucket(remoteChainSelector, isOutgoingLane)._consume(value, address(0)); } /// @notice Retrieves the token value for a token using the PriceRegistry @@ -154,15 +149,15 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, OwnerIsCreator { /// @notice Gets the token bucket with its values for the block it was requested at. /// @param remoteChainSelector chain selector to retrieve state for - /// @param isOutgoingLane if set to true, fetches the rate limit for the outgoing message lane (OnRamp). Otherwise fetches for the incoming message lane (OffRamp). + /// @param isOutgoingLane if set to true, fetches the rate limit state for the outgoing message lane (OnRamp). + /// Otherwise fetches for the incoming message lane (OffRamp). /// The outgoing and incoming message rate limit state is completely separated. /// @return The token bucket. function currentRateLimiterState( uint64 remoteChainSelector, bool isOutgoingLane ) external view returns (RateLimiter.TokenBucket memory) { - return s_rateLimitersByChainSelector[_getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane)] - ._currentTokenBucketState(); + return _getTokenBucket(remoteChainSelector, isOutgoingLane)._currentTokenBucketState(); } /// @notice Applies the provided rate limiter config updates. @@ -185,19 +180,24 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, OwnerIsCreator { } bool isOutgoingLane = updateArgs.isOutgoingLane; - uint72 remoteChainSelectorWithDirection = _getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane); - RateLimiter.TokenBucket storage tokenBucket = s_rateLimitersByChainSelector[remoteChainSelectorWithDirection]; + RateLimiter.TokenBucket storage tokenBucket = _getTokenBucket(remoteChainSelector, isOutgoingLane); if (tokenBucket.lastUpdated == 0) { // Token bucket needs to be newly added - s_rateLimitersByChainSelector[remoteChainSelectorWithDirection] = RateLimiter.TokenBucket({ + RateLimiter.TokenBucket memory newTokenBucket = RateLimiter.TokenBucket({ rate: configUpdate.rate, capacity: configUpdate.capacity, tokens: configUpdate.capacity, lastUpdated: uint32(block.timestamp), isEnabled: configUpdate.isEnabled }); + + if (isOutgoingLane) { + s_rateLimitersByChainSelector[remoteChainSelector].outgoingLaneBucket = newTokenBucket; + } else { + s_rateLimitersByChainSelector[remoteChainSelector].incomingLaneBucket = newTokenBucket; + } } else { tokenBucket._setTokenBucketConfig(configUpdate); } diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index ba0ddac2e2..d7fd79f512 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -19,8 +19,4 @@ contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { function getTokenValue(Client.EVMTokenAmount memory tokenAmount) public view returns (uint256) { return _getTokenValue(tokenAmount); } - - function getChainSelectorWithDirection(uint64 remoteChainSelector, bool isOutgoingLane) public view returns (uint72) { - return _getChainSelectorWithDirection(remoteChainSelector, isOutgoingLane); - } } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 075ff29992..9a958c168d 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -179,24 +179,6 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup } } -contract MultiAggregateRateLimiter_getChainSelectorWithDirection is MultiAggregateRateLimiterSetup { - function test_IncomingLane_Fuzz_Success(uint64 remoteChainSelector) public view { - uint72 remoteChainSelectorWithDirection = s_rateLimiter.getChainSelectorWithDirection(remoteChainSelector, true); - - // 1 << 64 | remoteChainSelector should be equivalent to ((2^64) + remoteChianSelector) - uint72 expectedRemoteChainSelector = uint72(type(uint64).max) + 1 + remoteChainSelector; - assertEq(remoteChainSelectorWithDirection, expectedRemoteChainSelector); - - // Should never clash with the remoteChainSelector - assertNotEq(remoteChainSelectorWithDirection, remoteChainSelector); - } - - function test_OutgoingLane_Fuzz_Success(uint64 remoteChainSelector) public view { - uint72 remoteChainSelectorWithDirection = s_rateLimiter.getChainSelectorWithDirection(remoteChainSelector, false); - assertEq(remoteChainSelectorWithDirection, remoteChainSelector); - } -} - contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiterSetup { function test_Owner_Success() public { address newAddress = address(42); From f3b7b819ed5a24cefa74d5c6677aa45ff4a33ae5 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Tue, 28 May 2024 12:08:51 +0200 Subject: [PATCH 21/23] chore: generate wrappers --- contracts/gas-snapshots/ccip.gas-snapshot | 105 +- .../scripts/native_solc_compile_all_ccip | 1 + .../evm_2_evm_multi_offramp.go | 2 +- .../multi_aggregate_rate_limiter.go | 1830 +++++++++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 3 +- core/gethwrappers/ccip/go_generate.go | 1 + 6 files changed, 1878 insertions(+), 64 deletions(-) create mode 100644 core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index e07de05251..54302fca54 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -457,55 +457,50 @@ MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60758) MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126294) MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63302) MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 43853) -MultiAggregateRateLimiter__getTokenValue:test_GetTokenValue_Success() (gas: 19632) -MultiAggregateRateLimiter__getTokenValue:test_NoTokenPrice_Reverts() (gas: 21221) -MultiAggregateRateLimiter__rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16940) +MultiAggregateRateLimiter__getTokenValue:test_GetTokenValue_Success() (gas: 19595) +MultiAggregateRateLimiter__getTokenValue:test_NoTokenPrice_Reverts() (gas: 21180) +MultiAggregateRateLimiter__rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 17228) MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValueDifferentChainSelectors_Success() (gas: 9223372036854754743) -MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValue_Success_gas() (gas: 18930) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 187973) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByAdminOrOwner_Revert() (gas: 19288) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigByAdmin_Success() (gas: 77119) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 74584) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 35314) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 37198) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 16890) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12353) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1923613) -MultiAggregateRateLimiter_constructor:test_ConstructorNoConfigs_Success() (gas: 1974067) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2092466) -MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 20062) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 44668) -MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15672) -MultiAggregateRateLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10553) -MultiAggregateRateLimiter_setAdmin:test_Admin_Success() (gas: 19485) -MultiAggregateRateLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13037) -MultiAggregateRateLimiter_setAdmin:test_Owner_Success() (gas: 19039) -MultiAggregateRateLimiter_setAuthorizedCallers:test_AddAndRemove_Success() (gas: 75740) -MultiAggregateRateLimiter_setAuthorizedCallers:test_AddThenRemove_Success() (gas: 30978) -MultiAggregateRateLimiter_setAuthorizedCallers:test_ChangedByAdmin_Success() (gas: 18091) -MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyAdd_Success() (gas: 68891) -MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyOwnerOrAdmin_Revert() (gas: 15326) -MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyRemove_Success() (gas: 18648) -MultiAggregateRateLimiter_setAuthorizedCallers:test_SkipRemove_Success() (gas: 17707) -MultiAggregateRateLimiter_setAuthorizedCallers:test_ZeroAddressAdd_Revert() (gas: 12646) -MultiAggregateRateLimiter_setPriceRegistry:test_Admin_Success() (gas: 21492) -MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwnerOrAdmin_Revert() (gas: 13016) -MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19024) -MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10562) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18880) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensByAdmin_Success() (gas: 201288) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 161248) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_Success() (gas: 198751) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 17207) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 17262) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14428) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 64621) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithNoTokens_Success() (gas: 15140) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 66104) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50047) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 77710) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 88029) -MultiAggregateRateLimiter_validateIncomingMessage:test_ValidateMessageWithTokens_Success() (gas: 54987) +MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValueDifferentLanes_Success() (gas: 9223372036854754743) +MultiAggregateRateLimiter__rateLimitValue:test_RateLimitValue_Success_gas() (gas: 18769) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132024) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 311954) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17713) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutgoing_Success() (gas: 75754) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 75758) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38158) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 49117) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17033) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12352) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1916532) +MultiAggregateRateLimiter_constructor:test_ConstructorNoConfigs_Success() (gas: 2034259) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2213795) +MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 34248) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47383) +MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15806) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14555) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 64038) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageWithNoTokens_Success() (gas: 15267) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 67187) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50297) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 77910) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 87938) +MultiAggregateRateLimiter_onIncomingMessage:test_ValidateMessageWithTokens_Success() (gas: 54460) +MultiAggregateRateLimiter_setAuthorizedCallers:test_AddAndRemove_Success() (gas: 120460) +MultiAggregateRateLimiter_setAuthorizedCallers:test_AddThenRemove_Success() (gas: 65981) +MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyAdd_Success() (gas: 133162) +MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyOwner_Revert() (gas: 13615) +MultiAggregateRateLimiter_setAuthorizedCallers:test_OnlyRemove_Success() (gas: 45684) +MultiAggregateRateLimiter_setAuthorizedCallers:test_SkipRemove_Success() (gas: 32621) +MultiAggregateRateLimiter_setAuthorizedCallers:test_ZeroAddressAdd_Revert() (gas: 12621) +MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwner_Revert() (gas: 11336) +MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19124) +MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10608) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 17104) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 161147) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_Success() (gas: 198653) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 17139) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 17194) MultiCommitStore_applySourceChainConfigUpdates:test_InvalidSourceChainConfig_Revert() (gas: 29592) MultiCommitStore_applySourceChainConfigUpdates:test_OnlyOwner_Revert() (gas: 12743) MultiCommitStore_constructor:test_Constructor_Failure() (gas: 316394) @@ -662,20 +657,6 @@ RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 275862) RMN_voteToCurse:test_InvalidVoter_Revert() (gas: 13671) RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 194189) RMN_voteToCurse:test_VoteToCurseSuccess_gas() (gas: 70265) -RateLimiterNoEvents_constructor:test_Constructor_Success() (gas: 19585) -RateLimiterNoEvents_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 15837) -RateLimiterNoEvents_consume:test_AggregateValueRateLimitReached_Revert() (gas: 21074) -RateLimiterNoEvents_consume:test_ConsumeAggregateValue_Success() (gas: 28738) -RateLimiterNoEvents_consume:test_ConsumeTokens_Success() (gas: 15351) -RateLimiterNoEvents_consume:test_ConsumeUnlimited_Success() (gas: 36730) -RateLimiterNoEvents_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15642) -RateLimiterNoEvents_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 22954) -RateLimiterNoEvents_consume:test_Refill_Success() (gas: 32145) -RateLimiterNoEvents_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18171) -RateLimiterNoEvents_consume:test_TokenRateLimitReached_Revert() (gas: 23552) -RateLimiterNoEvents_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 36843) -RateLimiterNoEvents_currentTokenBucketState:test_Refill_Success() (gas: 44480) -RateLimiterNoEvents_setTokenBucketConfig:test_SetRateLimiterNoEventsConfig_Success() (gas: 33866) RateLimiter_constructor:test_Constructor_Success() (gas: 19650) RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 15916) RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22222) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 2bfb7ca0d6..0e3b5975e4 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -52,6 +52,7 @@ compileContractLowOpts ccip/onRamp/EVM2EVMMultiOnRamp.sol compileContractLowOpts ccip/onRamp/EVM2EVMOnRamp.sol compileContract ccip/CommitStore.sol compileContract ccip/MultiCommitStore.sol +compileContract ccip/MultiAggregateRateLimiter.sol compileContract ccip/Router.sol compileContract ccip/PriceRegistry.sol compileContract ccip/pools/LockReleaseTokenPool.sol diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go index 2a82589626..fb853b2c0b 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go @@ -98,7 +98,7 @@ type InternalExecutionReportSingleChain struct { var EVM2EVMMultiOffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"InvalidMessageId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"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\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedSenderWithPreviousRampMessageInflight\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"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\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setOCR2Config\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162005e3038038062005e30833981016040819052620000359162000678565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200012c565b5050466080525081516001600160a01b0316620000ef576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160a01b0390811660a05260208301516001600160401b031660c05260408301511660e0526200012481620001d7565b505062000850565b336001600160a01b03821603620001865760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156200053a576000828281518110620001fb57620001fb620007e3565b60200260200101519050600081600001519050806001600160401b0316600003620002455760405163c39a620560e01b81526001600160401b038216600482015260240162000083565b60608201516001600160a01b031662000271576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260096020526040902060018101546001600160a01b0316620004395760a0516040516374eb454760e11b81526001600160401b03841660048201526000916001600160a01b03169063e9d68a8e90602401606060405180830381865afa158015620002ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003159190620007f9565b905083606001516001600160a01b031681604001516001600160a01b03161415806200034d575060208101516001600160401b031615155b15620003785760405163c39a620560e01b81526001600160401b038416600482015260240162000083565b620003af8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36200053e60201b60201c565b600283015560608401516001830180546001600160a01b0319166001600160a01b039283161790556040808601518454610100600160a81b0319166101009190931602919091178355516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150620004a0565b606083015160018201546001600160a01b0390811691161415806200047557506040830151815461010090046001600160a01b03908116911614155b15620004a05760405163c39a620560e01b81526001600160401b038316600482015260240162000083565b6020830151815490151560ff199091161781556040516001600160401b038316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af07927849062000523908490815460ff81161515825260081c6001600160a01b0390811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050620001da565b5050565b60c05160408051602081018490526001600160401b0380871692820192909252911660608201526001600160a01b038316608082015260009060a0016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620005d457620005d462000599565b60405290565b604051608081016001600160401b0381118282101715620005d457620005d462000599565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a62000599565b604052919050565b80516001600160a01b03811681146200064a57600080fd5b919050565b80516001600160401b03811681146200064a57600080fd5b805180151581146200064a57600080fd5b6000808284036080808212156200068e57600080fd5b6060808312156200069e57600080fd5b620006a8620005af565b9250620006b58662000632565b83526020620006c68188016200064f565b818501526040620006da6040890162000632565b604086015260608801519496506001600160401b0380861115620006fd57600080fd5b858901955089601f8701126200071257600080fd5b85518181111562000727576200072762000599565b62000737848260051b01620005ff565b818152848101925060079190911b87018401908b8211156200075857600080fd5b968401965b81881015620007d15786888d031215620007775760008081fd5b62000781620005da565b6200078c896200064f565b81526200079b868a0162000667565b86820152620007ac858a0162000632565b85820152620007bd878a0162000632565b81880152835296860196918401916200075d565b80985050505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b6000606082840312156200080c57600080fd5b62000816620005af565b620008218362000667565b815262000831602084016200064f565b6020820152620008446040840162000632565b60408201529392505050565b60805160a05160c05160e051615560620008d0600039600081816101d4015281816117aa01526124e90152600081816101a4015281816117840152612f2f0152600081816101680152818161175601528181611aab01526127de015260008181610a5a01528181610aa601528181610eff0152610f4b01526155606000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806381ff7048116100b2578063afcb95d711610081578063e9d68a8e11610066578063e9d68a8e14610491578063f2fde38b14610583578063f52121a51461059657600080fd5b8063afcb95d71461045e578063b1dc65a41461047e57600080fd5b806381ff7048146103cc57806385572ffb146103fc5780638b3643341461040a5780638da5cb5b1461043657600080fd5b80635e36480c116101095780637437ff9f116100ee5780637437ff9f146102cd57806379ba5097146103b15780637f63b711146103b957600080fd5b80635e36480c14610298578063666cab8d146102b857600080fd5b806306285c691461013b578063181f5a77146102275780631ef3817414610270578063542625af14610285575b600080fd5b610211604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161021e9190613a7e565b60405180910390f35b6102636040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b60405161021e9190613b31565b61028361027e366004613e0f565b6105a9565b005b6102836102933660046143d5565b610a57565b6102ab6102a6366004614500565b610c7f565b60405161021e91906145a3565b6102c0610d13565b60405161021e9190614603565b6103a46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260075463ffffffff808216835264010000000080830473ffffffffffffffffffffffffffffffffffffffff90811660208601527801000000000000000000000000000000000000000000000000840461ffff16958501959095527a0100000000000000000000000000000000000000000000000000009092048116606084015260085490811660808401520490911660a082015290565b60405161021e9190614616565b610283610d82565b6102836103c7366004614685565b610e7f565b6004546002546040805163ffffffff8085168252640100000000909404909316602084015282015260600161021e565b610283610136366004614769565b61041d6104183660046147a4565b610e93565b60405167ffffffffffffffff909116815260200161021e565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161021e565b60408051600181526000602082018190529181019190915260600161021e565b61028361048c366004614817565b610ea9565b61053361049f3660046148fc565b6040805160808101825260008082526020820181905291810182905260608101919091525067ffffffffffffffff166000908152600960209081526040918290208251608081018452815460ff81161515825273ffffffffffffffffffffffffffffffffffffffff610100909104811693820193909352600182015490921692820192909252600290910154606082015290565b6040805182511515815260208084015173ffffffffffffffffffffffffffffffffffffffff908116918301919091528383015116918101919091526060918201519181019190915260800161021e565b610283610591366004614919565b61113a565b6102836105a4366004614936565b61114b565b84518460ff16601f82111561061f576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f6f206d616e79207472616e736d697474657273000000000000000000000060448201526064015b60405180910390fd5b80600003610689576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610616565b610691611542565b61069a856115c5565b60065460005b8181101561071e5760056000600683815481106106bf576106bf61499a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016106a0565b50875160005b818110156109145760008a82815181106107405761074061499a565b602002602001015190506000600281111561075d5761075d614539565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561079c5761079c614539565b14610803576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610616565b73ffffffffffffffffffffffffffffffffffffffff8116610850576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561090057610900614539565b021790555090505050806001019050610724565b5088516109289060069060208c01906139e8565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908b1617179055600480546109ae9146913091906000906109809063ffffffff166149f8565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168d8d8d8d8d8d611809565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168e8e8e8e8e8e604051610a4299989796959493929190614a1b565b60405180910390a15050505050505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610ae2576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff46166024820152604401610616565b815181518114610b1e576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610c6f576000848281518110610b3d57610b3d61499a565b60200260200101519050600081602001515190506000858481518110610b6557610b6561499a565b6020026020010151905080518214610ba9576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610c60576000828281518110610bc857610bc861499a565b6020026020010151905080600014158015610c03575084602001518281518110610bf457610bf461499a565b60200260200101516080015181105b15610c575784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810183905260448101829052606401610616565b50600101610bac565b50505050806001019050610b21565b50610c7a83836118b4565b505050565b6000610c8d60016004614ab1565b6002610c9a608085614af3565b67ffffffffffffffff16610cae9190614b1a565b67ffffffffffffffff85166000908152600b6020526040812090610cd3608087614b31565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c166003811115610d0a57610d0a614539565b90505b92915050565b60606006805480602002602001604051908101604052809291908181526020018280548015610d7857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d4d575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610616565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e87611542565b610e9081611964565b50565b600080610ea08484611e15565b50949350505050565b610eb38787611f45565b600254883590808214610efc576040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610616565b467f000000000000000000000000000000000000000000000000000000000000000014610f7d576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610616565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526005602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561100557611005614539565b600281111561101657611016614539565b905250905060028160200151600281111561103357611033614539565b14801561107a57506006816000015160ff16815481106110555761105561499a565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6110b0576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006110be856020614b1a565b6110c9886020614b1a565b6110d58b610144614b58565b6110df9190614b58565b6110e99190614b58565b905036811461112d576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610616565b5050505050505050505050565b611142611542565b610e9081611f8c565b333014611184576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201909252816111c1565b604080518082019091526000808252602082015281526020019060019003908161119a5790505b50610140840151519091501561127a576101408301516040805160608101909152602085015173ffffffffffffffffffffffffffffffffffffffff16608082015261127791908060a08101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252875167ffffffffffffffff1660208301528781015173ffffffffffffffffffffffffffffffffffffffff1691015261016086015185612081565b90505b6101208301515115801561129057506080830151155b806112b45750604083015173ffffffffffffffffffffffffffffffffffffffff163b155b80611301575060408301516112ff9073ffffffffffffffffffffffffffffffffffffffff167f85572ffb000000000000000000000000000000000000000000000000000000006123e3565b155b1561130b57505050565b600061131784836123ff565b600854909150640100000000900473ffffffffffffffffffffffffffffffffffffffff168015611426576040517f9e6bd42300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821690639e6bd42390611393908590600401614c2c565b600060405180830381600087803b1580156113ad57600080fd5b505af19250505080156113be575060015b611426573d8080156113ec576040519150601f19603f3d011682016040523d82523d6000602084013e6113f1565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b600754608086015160408088015190517f3cf97983000000000000000000000000000000000000000000000000000000008152600093849364010000000090910473ffffffffffffffffffffffffffffffffffffffff1692633cf979839261149692899261138892600401614c3f565b6000604051808303816000875af11580156114b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114fb9190810190614ccd565b50915091508161153957806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610616565b565b6000818060200190518101906115db9190614d3b565b602081015190915073ffffffffffffffffffffffffffffffffffffffff1661162f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516007805460208085015160408087015160608089015163ffffffff9081167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff61ffff909416780100000000000000000000000000000000000000000000000002939093167fffff000000000000ffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff9687166401000000009081027fffffffffffffffff0000000000000000000000000000000000000000000000009a8b169c85169c909c179b909b1716179290921790965560808801516008805460a08b015186169099029890961691161795909517909255835192830184527f00000000000000000000000000000000000000000000000000000000000000008216835267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016908301527f0000000000000000000000000000000000000000000000000000000000000000168183015290517f1c86233479b9d798a31091d42b1a954067dcd6c898553d63bf993757d2a90aff916117fd918490614de7565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a60405160200161182d99989796959493929190614e9b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b81516000036118ee576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561195d576119558582815181106119235761192361499a565b60200260200101518461194f578583815181106119425761194261499a565b60200260200101516124af565b836124af565b600101611905565b5050505050565b60005b8151811015611e115760008282815181106119845761198461499a565b602002602001015190506000816000015190508067ffffffffffffffff166000036119e7576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b606082015173ffffffffffffffffffffffffffffffffffffffff16611a38576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600960205260409020600181015473ffffffffffffffffffffffffffffffffffffffff16611cb5576040517fe9d68a8e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9d68a8e90602401606060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190614f30565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16141580611b7d5750602081015167ffffffffffffffff1615155b15611bc0576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b611bef8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3612f29565b600283015560608401516001830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92831617905560408086015184547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010091909316029190911783555167ffffffffffffffff841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150611d4d565b6060830151600182015473ffffffffffffffffffffffffffffffffffffffff9081169116141580611d0a575060408301518154610100900473ffffffffffffffffffffffffffffffffffffffff908116911614155b15611d4d576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610616565b602083015181549015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617815560405167ffffffffffffffff8316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af079278490611dfb908490815460ff81161515825260081c73ffffffffffffffffffffffffffffffffffffffff90811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050611967565b5050565b67ffffffffffffffff8083166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091829116808203611f375767ffffffffffffffff8516600090815260096020526040902054610100900473ffffffffffffffffffffffffffffffffffffffff168015611f35576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015282169063856c824790602401602060405180830381865afa158015611f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f289190614f84565b6001935093505050611f3e565b505b9150600090505b9250929050565b6000611f5382840184614fa1565b60408051600080825260208201909252919250610c7a918391611f86565b6060815260200190600190039081611f715790505b506118b4565b3373ffffffffffffffffffffffffffffffffffffffff82160361200b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610616565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8360005b8551811015610ea05760008482815181106120a2576120a261499a565b60200260200101518060200190518101906120bd9190614fd6565b905060006120ce8260200151612fb9565b905061211073ffffffffffffffffffffffffffffffffffffffff82167faff2afbf000000000000000000000000000000000000000000000000000000006123e3565b61215e576040517fae9b4ce900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610616565b6000806122ab634059f55b60e01b6040518060e001604052808c6000015181526020018c6020015167ffffffffffffffff1681526020018c6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018d89815181106121c7576121c761499a565b602002602001015160200151815260200187600001518152602001876040015181526020018a89815181106121fe576121fe61499a565b6020026020010151815250604051602401612219919061508b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152600854859063ffffffff166113886084613014565b5091509150816122e957806040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b8051604014612333578051604080517f78ef802400000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604401610616565b6000808280602001905181019061234a9190615165565b915091506123578261313a565b8888815181106123695761236961499a565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808888815181106123ba576123ba61499a565b60200260200101516020018181525050505050505050806001019050612085565b949350505050565b60006123ee836131d1565b8015610d0a5750610d0a8383613235565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff1681526020018460200151604051602001612484919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b81516040517f58babe3300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906358babe3390602401602060405180830381865afa158015612545573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125699190615189565b156125ac576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b60208301515160008190036125ec576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836040015151811461262a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff82166000908152600960205260409020805460ff1661268a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b60008267ffffffffffffffff8111156126a5576126a5613b44565b6040519080825280602002602001820160405280156126ce578160200160208202803683370190505b50905060005b83811015612793576000876020015182815181106126f4576126f461499a565b6020026020010151905061270c818560020154613304565b83838151811061271e5761271e61499a565b6020026020010181815250508061018001518383815181106127425761274261499a565b60200260200101511461278a578061018001516040517f345039be00000000000000000000000000000000000000000000000000000000815260040161061691815260200190565b506001016126d4565b50606086015160808701516040517ffe41448f00000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263fe41448f92612815928a9288926004016151d7565b602060405180830381865afa158015612832573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612856919061521e565b90508060000361289e576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610616565b8551151560005b85811015612f1e576000896020015182815181106128c5576128c561499a565b6020026020010151905060006128df898360600151610c7f565b905060028160038111156128f5576128f5614539565b0361294b5760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612f16565b600081600381111561295f5761295f614539565b148061297c5750600381600381111561297a5761297a614539565b145b6129cc5760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b8315612a955760075460009063ffffffff166129e88742614ab1565b1190508080612a0857506003826003811115612a0657612a06614539565b145b612a4a576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b166004820152602401610616565b8a8481518110612a5c57612a5c61499a565b6020026020010151600014612a8f578a8481518110612a7d57612a7d61499a565b60200260200101518360800181815250505b50612afa565b6000816003811115612aa957612aa9614539565b14612afa5760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b600080612b0b8b8560200151611e15565b915091508015612c2b5760c084015167ffffffffffffffff16612b2f836001615237565b67ffffffffffffffff1614612bbf5760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60405180910390a150505050612f16565b67ffffffffffffffff8b81166000908152600a602090815260408083208883015173ffffffffffffffffffffffffffffffffffffffff168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169184169190911790555b6000836003811115612c3f57612c3f614539565b03612cdd5760c084015167ffffffffffffffff16612c5e836001615237565b67ffffffffffffffff1614612cdd5760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60008d604001518681518110612cf557612cf561499a565b60200260200101519050612d238561018001518d87606001518861014001515189610120015151865161348a565b612d338c866060015160016135e6565b600080612d4087846136c4565b91509150612d538e8860600151846135e6565b888015612d7157506003826003811115612d6f57612d6f614539565b145b15612db157866101800151816040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b6003826003811115612dc557612dc5614539565b14158015612de557506002826003811115612de257612de2614539565b14155b15612e26578d8760600151836040517f926c5a3e00000000000000000000000000000000000000000000000000000000815260040161061693929190615278565b6000866003811115612e3a57612e3a614539565b03612eb55767ffffffffffffffff808f166000908152600a602090815260408083208b83015173ffffffffffffffffffffffffffffffffffffffff168452909152812080549092169190612e8d8361529e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051612f069291906152bb565b60405180910390a4505050505050505b6001016128a5565b505050505050505050565b600081847f000000000000000000000000000000000000000000000000000000000000000085604051602001612f99949392919093845267ffffffffffffffff92831660208501529116604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b60008151602014612ff857816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b610d0d8280602001905181019061300f919061521e565b61313a565b6000606060008361ffff1667ffffffffffffffff81111561303757613037613b44565b6040519080825280601f01601f191660200182016040528015613061576020820181803683370190505b509150863b613094577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a858110156130c7577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613100577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156131235750835b808352806000602085013e50955095509592505050565b600073ffffffffffffffffffffffffffffffffffffffff82118061315e5750600a82105b156131cd57604080516020810184905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261061691600401613b31565b5090565b60006131fd827f01ffc9a700000000000000000000000000000000000000000000000000000000613235565b8015610d0d575061322e827fffffffff00000000000000000000000000000000000000000000000000000000613235565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132ed575060208210155b80156132f95750600081115b979650505050505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016133a798979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016133e091906152db565b6040516020818303038152906040528051906020012087610160015160405160200161340c9190615366565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b6007547801000000000000000000000000000000000000000000000000900461ffff168311156134fa576040517fa1e5205a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b808314613547576040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b6007547a010000000000000000000000000000000000000000000000000000900463ffffffff168211156135de576007546040517f1fd8fd04000000000000000000000000000000000000000000000000000000008152600481018890527a01000000000000000000000000000000000000000000000000000090910463ffffffff16602482015260448101839052606401610616565b505050505050565b600060026135f5608085614af3565b67ffffffffffffffff166136099190614b1a565b67ffffffffffffffff85166000908152600b602052604081209192509081613632608087614b31565b67ffffffffffffffff16815260208101919091526040016000205490508161365c60016004614ab1565b901b19168183600381111561367357613673614539565b67ffffffffffffffff87166000908152600b602052604081209190921b929092179182916136a2608088614b31565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a5906137089087908790600401615379565b600060405180830381600087803b15801561372257600080fd5b505af1925050508015613733575060015b6139cd573d808015613761576040519150601f19603f3d011682016040523d82523d6000602084013e613766565b606091505b50600061377282615503565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216148061380557507fe1cd5509000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061385157507f8d666f60000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061389d57507f78ef8024000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b806138e957507f0c3b563c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061393557507fae9b4ce9000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061398157507f09c25325000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b156139925750600392509050611f3e565b856101800151826040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b50506040805160208101909152600081526002909250929050565b828054828255906000526020600020908101928215613a62579160200282015b82811115613a6257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613a08565b506131cd9291505b808211156131cd5760008155600101613a6a565b60608101610d0d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b60005b83811015613ade578181015183820152602001613ac6565b50506000910152565b60008151808452613aff816020860160208601613ac3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d0a6020830184613ae7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405290565b6040516101a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405160a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516080810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516060810167ffffffffffffffff81118282101715613b9657613b96613b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c7057613c70613b44565b604052919050565b600067ffffffffffffffff821115613c9257613c92613b44565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114610e9057600080fd5b8035613cc981613c9c565b919050565b600082601f830112613cdf57600080fd5b81356020613cf4613cef83613c78565b613c29565b8083825260208201915060208460051b870101935086841115613d1657600080fd5b602086015b84811015613d3b578035613d2e81613c9c565b8352918301918301613d1b565b509695505050505050565b803560ff81168114613cc957600080fd5b600067ffffffffffffffff821115613d7157613d71613b44565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613dae57600080fd5b8135613dbc613cef82613d57565b818152846020838601011115613dd157600080fd5b816020850160208301376000918101602001919091529392505050565b67ffffffffffffffff81168114610e9057600080fd5b8035613cc981613dee565b60008060008060008060c08789031215613e2857600080fd5b863567ffffffffffffffff80821115613e4057600080fd5b613e4c8a838b01613cce565b97506020890135915080821115613e6257600080fd5b613e6e8a838b01613cce565b9650613e7c60408a01613d46565b95506060890135915080821115613e9257600080fd5b613e9e8a838b01613d9d565b9450613eac60808a01613e04565b935060a0890135915080821115613ec257600080fd5b50613ecf89828a01613d9d565b9150509295509295509295565b8015158114610e9057600080fd5b8035613cc981613edc565b600082601f830112613f0657600080fd5b81356020613f16613cef83613c78565b82815260069290921b84018101918181019086841115613f3557600080fd5b8286015b84811015613d3b5760408189031215613f525760008081fd5b613f5a613b73565b8135613f6581613c9c565b81528185013585820152835291830191604001613f39565b600082601f830112613f8e57600080fd5b81356020613f9e613cef83613c78565b82815260059290921b84018101918181019086841115613fbd57600080fd5b8286015b84811015613d3b57803567ffffffffffffffff811115613fe15760008081fd5b613fef8986838b0101613d9d565b845250918301918301613fc1565b60006101a0828403121561401057600080fd5b614018613b9c565b905061402382613e04565b815261403160208301613cbe565b602082015261404260408301613cbe565b604082015261405360608301613e04565b60608201526080820135608082015261406e60a08301613eea565b60a082015261407f60c08301613e04565b60c082015261409060e08301613cbe565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156140bd57600080fd5b6140c986838701613d9d565b838501526101409250828501359150808211156140e557600080fd5b6140f186838701613ef5565b8385015261016092508285013591508082111561410d57600080fd5b5061411a85828601613f7d565b82840152505061018080830135818301525092915050565b600082601f83011261414357600080fd5b81356020614153613cef83613c78565b82815260059290921b8401810191818101908684111561417257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156141965760008081fd5b6141a48986838b0101613ffd565b845250918301918301614176565b600082601f8301126141c357600080fd5b813560206141d3613cef83613c78565b82815260059290921b840181019181810190868411156141f257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156142165760008081fd5b6142248986838b0101613f7d565b8452509183019183016141f6565b600082601f83011261424357600080fd5b81356020614253613cef83613c78565b8083825260208201915060208460051b87010193508684111561427557600080fd5b602086015b84811015613d3b578035835291830191830161427a565b600082601f8301126142a257600080fd5b813560206142b2613cef83613c78565b82815260059290921b840181019181810190868411156142d157600080fd5b8286015b84811015613d3b57803567ffffffffffffffff808211156142f65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561432f5760008081fd5b614337613bc0565b614342888501613e04565b8152604080850135848111156143585760008081fd5b6143668e8b83890101614132565b8a840152506060808601358581111561437f5760008081fd5b61438d8f8c838a01016141b2565b83850152506080915081860135858111156143a85760008081fd5b6143b68f8c838a0101614232565b91840191909152509190930135908301525083529183019183016142d5565b60008060408084860312156143e957600080fd5b833567ffffffffffffffff8082111561440157600080fd5b61440d87838801614291565b945060209150818601358181111561442457600080fd5b8601601f8101881361443557600080fd5b8035614443613cef82613c78565b81815260059190911b8201840190848101908a83111561446257600080fd5b8584015b838110156144ee5780358681111561447e5760008081fd5b8501603f81018d136144905760008081fd5b878101356144a0613cef82613c78565b81815260059190911b82018a0190898101908f8311156144c05760008081fd5b928b01925b828410156144de5783358252928a0192908a01906144c5565b8652505050918601918601614466565b50809750505050505050509250929050565b6000806040838503121561451357600080fd5b823561451e81613dee565b9150602083013561452e81613dee565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061459f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60208101610d0d8284614568565b60008151808452602080850194506020840160005b838110156145f857815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016145c6565b509495945050505050565b602081526000610d0a60208301846145b1565b60c08101610d0d828463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b6000602080838503121561469857600080fd5b823567ffffffffffffffff8111156146af57600080fd5b8301601f810185136146c057600080fd5b80356146ce613cef82613c78565b81815260079190911b820183019083810190878311156146ed57600080fd5b928401925b828410156132f9576080848903121561470b5760008081fd5b614713613be3565b843561471e81613dee565b81528486013561472d81613edc565b8187015260408581013561474081613c9c565b9082015260608581013561475381613c9c565b90820152825260809390930192908401906146f2565b60006020828403121561477b57600080fd5b813567ffffffffffffffff81111561479257600080fd5b820160a08185031215612fb257600080fd5b600080604083850312156147b757600080fd5b82356147c281613dee565b9150602083013561452e81613c9c565b60008083601f8401126147e457600080fd5b50813567ffffffffffffffff8111156147fc57600080fd5b6020830191508360208260051b8501011115611f3e57600080fd5b60008060008060008060008060e0898b03121561483357600080fd5b606089018a81111561484457600080fd5b8998503567ffffffffffffffff8082111561485e57600080fd5b818b0191508b601f83011261487257600080fd5b81358181111561488157600080fd5b8c602082850101111561489357600080fd5b6020830199508098505060808b01359150808211156148b157600080fd5b6148bd8c838d016147d2565b909750955060a08b01359150808211156148d657600080fd5b506148e38b828c016147d2565b999c989b50969995989497949560c00135949350505050565b60006020828403121561490e57600080fd5b8135612fb281613dee565b60006020828403121561492b57600080fd5b8135612fb281613c9c565b6000806040838503121561494957600080fd5b823567ffffffffffffffff8082111561496157600080fd5b61496d86838701613ffd565b9350602085013591508082111561498357600080fd5b5061499085828601613f7d565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103614a1157614a116149c9565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a4b8184018a6145b1565b90508281036080840152614a5f81896145b1565b905060ff871660a084015282810360c0840152614a7c8187613ae7565b905067ffffffffffffffff851660e0840152828103610100840152614aa18185613ae7565b9c9b505050505050505050505050565b81810381811115610d0d57610d0d6149c9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680614b0e57614b0e614ac4565b92169190910692915050565b8082028115828204841417610d0d57610d0d6149c9565b600067ffffffffffffffff80841680614b4c57614b4c614ac4565b92169190910492915050565b80820180821115610d0d57610d0d6149c9565b60008151808452602080850194506020840160005b838110156145f8578151805173ffffffffffffffffffffffffffffffffffffffff1688528301518388015260409096019590820190600101614b80565b8051825267ffffffffffffffff60208201511660208301526000604082015160a06040850152614bf060a0850182613ae7565b905060608301518482036060860152614c098282613ae7565b91505060808301518482036080860152614c238282614b6b565b95945050505050565b602081526000610d0a6020830184614bbd565b608081526000614c526080830187614bbd565b61ffff95909516602083015250604081019290925273ffffffffffffffffffffffffffffffffffffffff16606090910152919050565b600082601f830112614c9957600080fd5b8151614ca7613cef82613d57565b818152846020838601011115614cbc57600080fd5b6123db826020830160208701613ac3565b600080600060608486031215614ce257600080fd5b8351614ced81613edc565b602085015190935067ffffffffffffffff811115614d0a57600080fd5b614d1686828701614c88565b925050604084015190509250925092565b805163ffffffff81168114613cc957600080fd5b600060c08284031215614d4d57600080fd5b60405160c0810181811067ffffffffffffffff82111715614d7057614d70613b44565b604052614d7c83614d27565b81526020830151614d8c81613c9c565b6020820152604083015161ffff81168114614da657600080fd5b6040820152614db760608401614d27565b6060820152614dc860808401614d27565b608082015260a0830151614ddb81613c9c565b60a08201529392505050565b6101208101614e2d8285805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b612fb2606083018463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614ee28285018b6145b1565b91508382036080850152614ef6828a6145b1565b915060ff881660a085015283820360c0850152614f138288613ae7565b90861660e08501528381036101008501529050614aa18185613ae7565b600060608284031215614f4257600080fd5b614f4a613c06565b8251614f5581613edc565b81526020830151614f6581613dee565b60208201526040830151614f7881613c9c565b60408201529392505050565b600060208284031215614f9657600080fd5b8151612fb281613dee565b600060208284031215614fb357600080fd5b813567ffffffffffffffff811115614fca57600080fd5b6123db84828501614291565b600060208284031215614fe857600080fd5b815167ffffffffffffffff8082111561500057600080fd5b908301906060828603121561501457600080fd5b61501c613c06565b82518281111561502b57600080fd5b61503787828601614c88565b82525060208301518281111561504c57600080fd5b61505887828601614c88565b60208301525060408301518281111561507057600080fd5b61507c87828601614c88565b60408301525095945050505050565b602081526000825160e060208401526150a8610100840182613ae7565b905067ffffffffffffffff602085015116604084015260408401516150e5606085018273ffffffffffffffffffffffffffffffffffffffff169052565b506060840151608084015260808401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160a086015261512a8383613ae7565b925060a08601519150808584030160c08601526151478383613ae7565b925060c08601519150808584030160e086015250614c238282613ae7565b6000806040838503121561517857600080fd5b505080516020909101519092909150565b60006020828403121561519b57600080fd5b8151612fb281613edc565b60008151808452602080850194506020840160005b838110156145f8578151875295820195908201906001016151bb565b67ffffffffffffffff851681526080602082015260006151fa60808301866151a6565b828103604084015261520c81866151a6565b91505082606083015295945050505050565b60006020828403121561523057600080fd5b5051919050565b67ffffffffffffffff818116838216019080821115615258576152586149c9565b5092915050565b8281526040602082015260006123db6040830184613ae7565b67ffffffffffffffff848116825283166020820152606081016123db6040830184614568565b600067ffffffffffffffff808316818103614a1157614a116149c9565b6152c58184614568565b6040602082015260006123db6040830184613ae7565b602081526000610d0a6020830184614b6b565b60008282518085526020808601955060208260051b8401016020860160005b84811015615359577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952615347838351613ae7565b9884019892509083019060010161530d565b5090979650505050505050565b602081526000610d0a60208301846152ee565b6040815261539460408201845167ffffffffffffffff169052565b600060208401516153bd606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604084015173ffffffffffffffffffffffffffffffffffffffff8116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c084015161010061542b8185018367ffffffffffffffff169052565b60e086015191506101206154568186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061014091508282860152808701519250506101a061016081818701526154866101e0870185613ae7565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06101808188870301818901526154c58686614b6b565b9550828a015194508188870301848901526154e086866152ee565b9550808a01516101c089015250505050508281036020840152614c2381856152ee565b6000815160208301517fffffffff000000000000000000000000000000000000000000000000000000008082169350600483101561554b5780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", + Bin: "0x6101006040523480156200001257600080fd5b5060405162005e3038038062005e30833981016040819052620000359162000678565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200012c565b5050466080525081516001600160a01b0316620000ef576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160a01b0390811660a05260208301516001600160401b031660c05260408301511660e0526200012481620001d7565b505062000850565b336001600160a01b03821603620001865760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156200053a576000828281518110620001fb57620001fb620007e3565b60200260200101519050600081600001519050806001600160401b0316600003620002455760405163c39a620560e01b81526001600160401b038216600482015260240162000083565b60608201516001600160a01b031662000271576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260096020526040902060018101546001600160a01b0316620004395760a0516040516374eb454760e11b81526001600160401b03841660048201526000916001600160a01b03169063e9d68a8e90602401606060405180830381865afa158015620002ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003159190620007f9565b905083606001516001600160a01b031681604001516001600160a01b03161415806200034d575060208101516001600160401b031615155b15620003785760405163c39a620560e01b81526001600160401b038416600482015260240162000083565b620003af8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36200053e60201b60201c565b600283015560608401516001830180546001600160a01b0319166001600160a01b039283161790556040808601518454610100600160a81b0319166101009190931602919091178355516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150620004a0565b606083015160018201546001600160a01b0390811691161415806200047557506040830151815461010090046001600160a01b03908116911614155b15620004a05760405163c39a620560e01b81526001600160401b038316600482015260240162000083565b6020830151815490151560ff199091161781556040516001600160401b038316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af07927849062000523908490815460ff81161515825260081c6001600160a01b0390811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050620001da565b5050565b60c05160408051602081018490526001600160401b0380871692820192909252911660608201526001600160a01b038316608082015260009060a0016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620005d457620005d462000599565b60405290565b604051608081016001600160401b0381118282101715620005d457620005d462000599565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a62000599565b604052919050565b80516001600160a01b03811681146200064a57600080fd5b919050565b80516001600160401b03811681146200064a57600080fd5b805180151581146200064a57600080fd5b6000808284036080808212156200068e57600080fd5b6060808312156200069e57600080fd5b620006a8620005af565b9250620006b58662000632565b83526020620006c68188016200064f565b818501526040620006da6040890162000632565b604086015260608801519496506001600160401b0380861115620006fd57600080fd5b858901955089601f8701126200071257600080fd5b85518181111562000727576200072762000599565b62000737848260051b01620005ff565b818152848101925060079190911b87018401908b8211156200075857600080fd5b968401965b81881015620007d15786888d031215620007775760008081fd5b62000781620005da565b6200078c896200064f565b81526200079b868a0162000667565b86820152620007ac858a0162000632565b85820152620007bd878a0162000632565b81880152835296860196918401916200075d565b80985050505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b6000606082840312156200080c57600080fd5b62000816620005af565b620008218362000667565b815262000831602084016200064f565b6020820152620008446040840162000632565b60408201529392505050565b60805160a05160c05160e051615560620008d0600039600081816101d4015281816117aa01526124e90152600081816101a4015281816117840152612f2f0152600081816101680152818161175601528181611aab01526127de015260008181610a5a01528181610aa601528181610eff0152610f4b01526155606000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806381ff7048116100b2578063afcb95d711610081578063e9d68a8e11610066578063e9d68a8e14610491578063f2fde38b14610583578063f52121a51461059657600080fd5b8063afcb95d71461045e578063b1dc65a41461047e57600080fd5b806381ff7048146103cc57806385572ffb146103fc5780638b3643341461040a5780638da5cb5b1461043657600080fd5b80635e36480c116101095780637437ff9f116100ee5780637437ff9f146102cd57806379ba5097146103b15780637f63b711146103b957600080fd5b80635e36480c14610298578063666cab8d146102b857600080fd5b806306285c691461013b578063181f5a77146102275780631ef3817414610270578063542625af14610285575b600080fd5b610211604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161021e9190613a7e565b60405180910390f35b6102636040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b60405161021e9190613b31565b61028361027e366004613e0f565b6105a9565b005b6102836102933660046143d5565b610a57565b6102ab6102a6366004614500565b610c7f565b60405161021e91906145a3565b6102c0610d13565b60405161021e9190614603565b6103a46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260075463ffffffff808216835264010000000080830473ffffffffffffffffffffffffffffffffffffffff90811660208601527801000000000000000000000000000000000000000000000000840461ffff16958501959095527a0100000000000000000000000000000000000000000000000000009092048116606084015260085490811660808401520490911660a082015290565b60405161021e9190614616565b610283610d82565b6102836103c7366004614685565b610e7f565b6004546002546040805163ffffffff8085168252640100000000909404909316602084015282015260600161021e565b610283610136366004614769565b61041d6104183660046147a4565b610e93565b60405167ffffffffffffffff909116815260200161021e565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161021e565b60408051600181526000602082018190529181019190915260600161021e565b61028361048c366004614817565b610ea9565b61053361049f3660046148fc565b6040805160808101825260008082526020820181905291810182905260608101919091525067ffffffffffffffff166000908152600960209081526040918290208251608081018452815460ff81161515825273ffffffffffffffffffffffffffffffffffffffff610100909104811693820193909352600182015490921692820192909252600290910154606082015290565b6040805182511515815260208084015173ffffffffffffffffffffffffffffffffffffffff908116918301919091528383015116918101919091526060918201519181019190915260800161021e565b610283610591366004614919565b61113a565b6102836105a4366004614936565b61114b565b84518460ff16601f82111561061f576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f6f206d616e79207472616e736d697474657273000000000000000000000060448201526064015b60405180910390fd5b80600003610689576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610616565b610691611542565b61069a856115c5565b60065460005b8181101561071e5760056000600683815481106106bf576106bf61499a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016106a0565b50875160005b818110156109145760008a82815181106107405761074061499a565b602002602001015190506000600281111561075d5761075d614539565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561079c5761079c614539565b14610803576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610616565b73ffffffffffffffffffffffffffffffffffffffff8116610850576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561090057610900614539565b021790555090505050806001019050610724565b5088516109289060069060208c01906139e8565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908b1617179055600480546109ae9146913091906000906109809063ffffffff166149f8565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168d8d8d8d8d8d611809565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168e8e8e8e8e8e604051610a4299989796959493929190614a1b565b60405180910390a15050505050505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610ae2576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff46166024820152604401610616565b815181518114610b1e576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610c6f576000848281518110610b3d57610b3d61499a565b60200260200101519050600081602001515190506000858481518110610b6557610b6561499a565b6020026020010151905080518214610ba9576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610c60576000828281518110610bc857610bc861499a565b6020026020010151905080600014158015610c03575084602001518281518110610bf457610bf461499a565b60200260200101516080015181105b15610c575784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810183905260448101829052606401610616565b50600101610bac565b50505050806001019050610b21565b50610c7a83836118b4565b505050565b6000610c8d60016004614ab1565b6002610c9a608085614af3565b67ffffffffffffffff16610cae9190614b1a565b67ffffffffffffffff85166000908152600b6020526040812090610cd3608087614b31565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c166003811115610d0a57610d0a614539565b90505b92915050565b60606006805480602002602001604051908101604052809291908181526020018280548015610d7857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d4d575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610616565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e87611542565b610e9081611964565b50565b600080610ea08484611e15565b50949350505050565b610eb38787611f45565b600254883590808214610efc576040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610616565b467f000000000000000000000000000000000000000000000000000000000000000014610f7d576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610616565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526005602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561100557611005614539565b600281111561101657611016614539565b905250905060028160200151600281111561103357611033614539565b14801561107a57506006816000015160ff16815481106110555761105561499a565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6110b0576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006110be856020614b1a565b6110c9886020614b1a565b6110d58b610144614b58565b6110df9190614b58565b6110e99190614b58565b905036811461112d576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610616565b5050505050505050505050565b611142611542565b610e9081611f8c565b333014611184576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201909252816111c1565b604080518082019091526000808252602082015281526020019060019003908161119a5790505b50610140840151519091501561127a576101408301516040805160608101909152602085015173ffffffffffffffffffffffffffffffffffffffff16608082015261127791908060a08101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252875167ffffffffffffffff1660208301528781015173ffffffffffffffffffffffffffffffffffffffff1691015261016086015185612081565b90505b6101208301515115801561129057506080830151155b806112b45750604083015173ffffffffffffffffffffffffffffffffffffffff163b155b80611301575060408301516112ff9073ffffffffffffffffffffffffffffffffffffffff167f85572ffb000000000000000000000000000000000000000000000000000000006123e3565b155b1561130b57505050565b600061131784836123ff565b600854909150640100000000900473ffffffffffffffffffffffffffffffffffffffff168015611426576040517fa219f6e500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063a219f6e590611393908590600401614c2c565b600060405180830381600087803b1580156113ad57600080fd5b505af19250505080156113be575060015b611426573d8080156113ec576040519150601f19603f3d011682016040523d82523d6000602084013e6113f1565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b600754608086015160408088015190517f3cf97983000000000000000000000000000000000000000000000000000000008152600093849364010000000090910473ffffffffffffffffffffffffffffffffffffffff1692633cf979839261149692899261138892600401614c3f565b6000604051808303816000875af11580156114b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114fb9190810190614ccd565b50915091508161153957806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610616565b565b6000818060200190518101906115db9190614d3b565b602081015190915073ffffffffffffffffffffffffffffffffffffffff1661162f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516007805460208085015160408087015160608089015163ffffffff9081167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff61ffff909416780100000000000000000000000000000000000000000000000002939093167fffff000000000000ffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff9687166401000000009081027fffffffffffffffff0000000000000000000000000000000000000000000000009a8b169c85169c909c179b909b1716179290921790965560808801516008805460a08b015186169099029890961691161795909517909255835192830184527f00000000000000000000000000000000000000000000000000000000000000008216835267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016908301527f0000000000000000000000000000000000000000000000000000000000000000168183015290517f1c86233479b9d798a31091d42b1a954067dcd6c898553d63bf993757d2a90aff916117fd918490614de7565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a60405160200161182d99989796959493929190614e9b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b81516000036118ee576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561195d576119558582815181106119235761192361499a565b60200260200101518461194f578583815181106119425761194261499a565b60200260200101516124af565b836124af565b600101611905565b5050505050565b60005b8151811015611e115760008282815181106119845761198461499a565b602002602001015190506000816000015190508067ffffffffffffffff166000036119e7576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b606082015173ffffffffffffffffffffffffffffffffffffffff16611a38576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600960205260409020600181015473ffffffffffffffffffffffffffffffffffffffff16611cb5576040517fe9d68a8e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9d68a8e90602401606060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190614f30565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16141580611b7d5750602081015167ffffffffffffffff1615155b15611bc0576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b611bef8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3612f29565b600283015560608401516001830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92831617905560408086015184547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010091909316029190911783555167ffffffffffffffff841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150611d4d565b6060830151600182015473ffffffffffffffffffffffffffffffffffffffff9081169116141580611d0a575060408301518154610100900473ffffffffffffffffffffffffffffffffffffffff908116911614155b15611d4d576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610616565b602083015181549015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617815560405167ffffffffffffffff8316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af079278490611dfb908490815460ff81161515825260081c73ffffffffffffffffffffffffffffffffffffffff90811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050611967565b5050565b67ffffffffffffffff8083166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091829116808203611f375767ffffffffffffffff8516600090815260096020526040902054610100900473ffffffffffffffffffffffffffffffffffffffff168015611f35576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015282169063856c824790602401602060405180830381865afa158015611f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f289190614f84565b6001935093505050611f3e565b505b9150600090505b9250929050565b6000611f5382840184614fa1565b60408051600080825260208201909252919250610c7a918391611f86565b6060815260200190600190039081611f715790505b506118b4565b3373ffffffffffffffffffffffffffffffffffffffff82160361200b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610616565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8360005b8551811015610ea05760008482815181106120a2576120a261499a565b60200260200101518060200190518101906120bd9190614fd6565b905060006120ce8260200151612fb9565b905061211073ffffffffffffffffffffffffffffffffffffffff82167faff2afbf000000000000000000000000000000000000000000000000000000006123e3565b61215e576040517fae9b4ce900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610616565b6000806122ab634059f55b60e01b6040518060e001604052808c6000015181526020018c6020015167ffffffffffffffff1681526020018c6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018d89815181106121c7576121c761499a565b602002602001015160200151815260200187600001518152602001876040015181526020018a89815181106121fe576121fe61499a565b6020026020010151815250604051602401612219919061508b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152600854859063ffffffff166113886084613014565b5091509150816122e957806040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b8051604014612333578051604080517f78ef802400000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604401610616565b6000808280602001905181019061234a9190615165565b915091506123578261313a565b8888815181106123695761236961499a565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808888815181106123ba576123ba61499a565b60200260200101516020018181525050505050505050806001019050612085565b949350505050565b60006123ee836131d1565b8015610d0a5750610d0a8383613235565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff1681526020018460200151604051602001612484919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b81516040517f58babe3300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906358babe3390602401602060405180830381865afa158015612545573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125699190615189565b156125ac576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b60208301515160008190036125ec576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836040015151811461262a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff82166000908152600960205260409020805460ff1661268a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b60008267ffffffffffffffff8111156126a5576126a5613b44565b6040519080825280602002602001820160405280156126ce578160200160208202803683370190505b50905060005b83811015612793576000876020015182815181106126f4576126f461499a565b6020026020010151905061270c818560020154613304565b83838151811061271e5761271e61499a565b6020026020010181815250508061018001518383815181106127425761274261499a565b60200260200101511461278a578061018001516040517f345039be00000000000000000000000000000000000000000000000000000000815260040161061691815260200190565b506001016126d4565b50606086015160808701516040517ffe41448f00000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263fe41448f92612815928a9288926004016151d7565b602060405180830381865afa158015612832573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612856919061521e565b90508060000361289e576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610616565b8551151560005b85811015612f1e576000896020015182815181106128c5576128c561499a565b6020026020010151905060006128df898360600151610c7f565b905060028160038111156128f5576128f5614539565b0361294b5760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612f16565b600081600381111561295f5761295f614539565b148061297c5750600381600381111561297a5761297a614539565b145b6129cc5760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b8315612a955760075460009063ffffffff166129e88742614ab1565b1190508080612a0857506003826003811115612a0657612a06614539565b145b612a4a576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b166004820152602401610616565b8a8481518110612a5c57612a5c61499a565b6020026020010151600014612a8f578a8481518110612a7d57612a7d61499a565b60200260200101518360800181815250505b50612afa565b6000816003811115612aa957612aa9614539565b14612afa5760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b600080612b0b8b8560200151611e15565b915091508015612c2b5760c084015167ffffffffffffffff16612b2f836001615237565b67ffffffffffffffff1614612bbf5760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60405180910390a150505050612f16565b67ffffffffffffffff8b81166000908152600a602090815260408083208883015173ffffffffffffffffffffffffffffffffffffffff168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169184169190911790555b6000836003811115612c3f57612c3f614539565b03612cdd5760c084015167ffffffffffffffff16612c5e836001615237565b67ffffffffffffffff1614612cdd5760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60008d604001518681518110612cf557612cf561499a565b60200260200101519050612d238561018001518d87606001518861014001515189610120015151865161348a565b612d338c866060015160016135e6565b600080612d4087846136c4565b91509150612d538e8860600151846135e6565b888015612d7157506003826003811115612d6f57612d6f614539565b145b15612db157866101800151816040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b6003826003811115612dc557612dc5614539565b14158015612de557506002826003811115612de257612de2614539565b14155b15612e26578d8760600151836040517f926c5a3e00000000000000000000000000000000000000000000000000000000815260040161061693929190615278565b6000866003811115612e3a57612e3a614539565b03612eb55767ffffffffffffffff808f166000908152600a602090815260408083208b83015173ffffffffffffffffffffffffffffffffffffffff168452909152812080549092169190612e8d8361529e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051612f069291906152bb565b60405180910390a4505050505050505b6001016128a5565b505050505050505050565b600081847f000000000000000000000000000000000000000000000000000000000000000085604051602001612f99949392919093845267ffffffffffffffff92831660208501529116604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b60008151602014612ff857816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b610d0d8280602001905181019061300f919061521e565b61313a565b6000606060008361ffff1667ffffffffffffffff81111561303757613037613b44565b6040519080825280601f01601f191660200182016040528015613061576020820181803683370190505b509150863b613094577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a858110156130c7577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613100577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156131235750835b808352806000602085013e50955095509592505050565b600073ffffffffffffffffffffffffffffffffffffffff82118061315e5750600a82105b156131cd57604080516020810184905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261061691600401613b31565b5090565b60006131fd827f01ffc9a700000000000000000000000000000000000000000000000000000000613235565b8015610d0d575061322e827fffffffff00000000000000000000000000000000000000000000000000000000613235565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132ed575060208210155b80156132f95750600081115b979650505050505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016133a798979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016133e091906152db565b6040516020818303038152906040528051906020012087610160015160405160200161340c9190615366565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b6007547801000000000000000000000000000000000000000000000000900461ffff168311156134fa576040517fa1e5205a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b808314613547576040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b6007547a010000000000000000000000000000000000000000000000000000900463ffffffff168211156135de576007546040517f1fd8fd04000000000000000000000000000000000000000000000000000000008152600481018890527a01000000000000000000000000000000000000000000000000000090910463ffffffff16602482015260448101839052606401610616565b505050505050565b600060026135f5608085614af3565b67ffffffffffffffff166136099190614b1a565b67ffffffffffffffff85166000908152600b602052604081209192509081613632608087614b31565b67ffffffffffffffff16815260208101919091526040016000205490508161365c60016004614ab1565b901b19168183600381111561367357613673614539565b67ffffffffffffffff87166000908152600b602052604081209190921b929092179182916136a2608088614b31565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a5906137089087908790600401615379565b600060405180830381600087803b15801561372257600080fd5b505af1925050508015613733575060015b6139cd573d808015613761576040519150601f19603f3d011682016040523d82523d6000602084013e613766565b606091505b50600061377282615503565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216148061380557507fe1cd5509000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061385157507f8d666f60000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061389d57507f78ef8024000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b806138e957507f0c3b563c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061393557507fae9b4ce9000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061398157507f09c25325000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b156139925750600392509050611f3e565b856101800151826040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b50506040805160208101909152600081526002909250929050565b828054828255906000526020600020908101928215613a62579160200282015b82811115613a6257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613a08565b506131cd9291505b808211156131cd5760008155600101613a6a565b60608101610d0d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b60005b83811015613ade578181015183820152602001613ac6565b50506000910152565b60008151808452613aff816020860160208601613ac3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d0a6020830184613ae7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405290565b6040516101a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405160a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516080810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516060810167ffffffffffffffff81118282101715613b9657613b96613b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c7057613c70613b44565b604052919050565b600067ffffffffffffffff821115613c9257613c92613b44565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114610e9057600080fd5b8035613cc981613c9c565b919050565b600082601f830112613cdf57600080fd5b81356020613cf4613cef83613c78565b613c29565b8083825260208201915060208460051b870101935086841115613d1657600080fd5b602086015b84811015613d3b578035613d2e81613c9c565b8352918301918301613d1b565b509695505050505050565b803560ff81168114613cc957600080fd5b600067ffffffffffffffff821115613d7157613d71613b44565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613dae57600080fd5b8135613dbc613cef82613d57565b818152846020838601011115613dd157600080fd5b816020850160208301376000918101602001919091529392505050565b67ffffffffffffffff81168114610e9057600080fd5b8035613cc981613dee565b60008060008060008060c08789031215613e2857600080fd5b863567ffffffffffffffff80821115613e4057600080fd5b613e4c8a838b01613cce565b97506020890135915080821115613e6257600080fd5b613e6e8a838b01613cce565b9650613e7c60408a01613d46565b95506060890135915080821115613e9257600080fd5b613e9e8a838b01613d9d565b9450613eac60808a01613e04565b935060a0890135915080821115613ec257600080fd5b50613ecf89828a01613d9d565b9150509295509295509295565b8015158114610e9057600080fd5b8035613cc981613edc565b600082601f830112613f0657600080fd5b81356020613f16613cef83613c78565b82815260069290921b84018101918181019086841115613f3557600080fd5b8286015b84811015613d3b5760408189031215613f525760008081fd5b613f5a613b73565b8135613f6581613c9c565b81528185013585820152835291830191604001613f39565b600082601f830112613f8e57600080fd5b81356020613f9e613cef83613c78565b82815260059290921b84018101918181019086841115613fbd57600080fd5b8286015b84811015613d3b57803567ffffffffffffffff811115613fe15760008081fd5b613fef8986838b0101613d9d565b845250918301918301613fc1565b60006101a0828403121561401057600080fd5b614018613b9c565b905061402382613e04565b815261403160208301613cbe565b602082015261404260408301613cbe565b604082015261405360608301613e04565b60608201526080820135608082015261406e60a08301613eea565b60a082015261407f60c08301613e04565b60c082015261409060e08301613cbe565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156140bd57600080fd5b6140c986838701613d9d565b838501526101409250828501359150808211156140e557600080fd5b6140f186838701613ef5565b8385015261016092508285013591508082111561410d57600080fd5b5061411a85828601613f7d565b82840152505061018080830135818301525092915050565b600082601f83011261414357600080fd5b81356020614153613cef83613c78565b82815260059290921b8401810191818101908684111561417257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156141965760008081fd5b6141a48986838b0101613ffd565b845250918301918301614176565b600082601f8301126141c357600080fd5b813560206141d3613cef83613c78565b82815260059290921b840181019181810190868411156141f257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156142165760008081fd5b6142248986838b0101613f7d565b8452509183019183016141f6565b600082601f83011261424357600080fd5b81356020614253613cef83613c78565b8083825260208201915060208460051b87010193508684111561427557600080fd5b602086015b84811015613d3b578035835291830191830161427a565b600082601f8301126142a257600080fd5b813560206142b2613cef83613c78565b82815260059290921b840181019181810190868411156142d157600080fd5b8286015b84811015613d3b57803567ffffffffffffffff808211156142f65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561432f5760008081fd5b614337613bc0565b614342888501613e04565b8152604080850135848111156143585760008081fd5b6143668e8b83890101614132565b8a840152506060808601358581111561437f5760008081fd5b61438d8f8c838a01016141b2565b83850152506080915081860135858111156143a85760008081fd5b6143b68f8c838a0101614232565b91840191909152509190930135908301525083529183019183016142d5565b60008060408084860312156143e957600080fd5b833567ffffffffffffffff8082111561440157600080fd5b61440d87838801614291565b945060209150818601358181111561442457600080fd5b8601601f8101881361443557600080fd5b8035614443613cef82613c78565b81815260059190911b8201840190848101908a83111561446257600080fd5b8584015b838110156144ee5780358681111561447e5760008081fd5b8501603f81018d136144905760008081fd5b878101356144a0613cef82613c78565b81815260059190911b82018a0190898101908f8311156144c05760008081fd5b928b01925b828410156144de5783358252928a0192908a01906144c5565b8652505050918601918601614466565b50809750505050505050509250929050565b6000806040838503121561451357600080fd5b823561451e81613dee565b9150602083013561452e81613dee565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061459f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60208101610d0d8284614568565b60008151808452602080850194506020840160005b838110156145f857815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016145c6565b509495945050505050565b602081526000610d0a60208301846145b1565b60c08101610d0d828463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b6000602080838503121561469857600080fd5b823567ffffffffffffffff8111156146af57600080fd5b8301601f810185136146c057600080fd5b80356146ce613cef82613c78565b81815260079190911b820183019083810190878311156146ed57600080fd5b928401925b828410156132f9576080848903121561470b5760008081fd5b614713613be3565b843561471e81613dee565b81528486013561472d81613edc565b8187015260408581013561474081613c9c565b9082015260608581013561475381613c9c565b90820152825260809390930192908401906146f2565b60006020828403121561477b57600080fd5b813567ffffffffffffffff81111561479257600080fd5b820160a08185031215612fb257600080fd5b600080604083850312156147b757600080fd5b82356147c281613dee565b9150602083013561452e81613c9c565b60008083601f8401126147e457600080fd5b50813567ffffffffffffffff8111156147fc57600080fd5b6020830191508360208260051b8501011115611f3e57600080fd5b60008060008060008060008060e0898b03121561483357600080fd5b606089018a81111561484457600080fd5b8998503567ffffffffffffffff8082111561485e57600080fd5b818b0191508b601f83011261487257600080fd5b81358181111561488157600080fd5b8c602082850101111561489357600080fd5b6020830199508098505060808b01359150808211156148b157600080fd5b6148bd8c838d016147d2565b909750955060a08b01359150808211156148d657600080fd5b506148e38b828c016147d2565b999c989b50969995989497949560c00135949350505050565b60006020828403121561490e57600080fd5b8135612fb281613dee565b60006020828403121561492b57600080fd5b8135612fb281613c9c565b6000806040838503121561494957600080fd5b823567ffffffffffffffff8082111561496157600080fd5b61496d86838701613ffd565b9350602085013591508082111561498357600080fd5b5061499085828601613f7d565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103614a1157614a116149c9565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a4b8184018a6145b1565b90508281036080840152614a5f81896145b1565b905060ff871660a084015282810360c0840152614a7c8187613ae7565b905067ffffffffffffffff851660e0840152828103610100840152614aa18185613ae7565b9c9b505050505050505050505050565b81810381811115610d0d57610d0d6149c9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680614b0e57614b0e614ac4565b92169190910692915050565b8082028115828204841417610d0d57610d0d6149c9565b600067ffffffffffffffff80841680614b4c57614b4c614ac4565b92169190910492915050565b80820180821115610d0d57610d0d6149c9565b60008151808452602080850194506020840160005b838110156145f8578151805173ffffffffffffffffffffffffffffffffffffffff1688528301518388015260409096019590820190600101614b80565b8051825267ffffffffffffffff60208201511660208301526000604082015160a06040850152614bf060a0850182613ae7565b905060608301518482036060860152614c098282613ae7565b91505060808301518482036080860152614c238282614b6b565b95945050505050565b602081526000610d0a6020830184614bbd565b608081526000614c526080830187614bbd565b61ffff95909516602083015250604081019290925273ffffffffffffffffffffffffffffffffffffffff16606090910152919050565b600082601f830112614c9957600080fd5b8151614ca7613cef82613d57565b818152846020838601011115614cbc57600080fd5b6123db826020830160208701613ac3565b600080600060608486031215614ce257600080fd5b8351614ced81613edc565b602085015190935067ffffffffffffffff811115614d0a57600080fd5b614d1686828701614c88565b925050604084015190509250925092565b805163ffffffff81168114613cc957600080fd5b600060c08284031215614d4d57600080fd5b60405160c0810181811067ffffffffffffffff82111715614d7057614d70613b44565b604052614d7c83614d27565b81526020830151614d8c81613c9c565b6020820152604083015161ffff81168114614da657600080fd5b6040820152614db760608401614d27565b6060820152614dc860808401614d27565b608082015260a0830151614ddb81613c9c565b60a08201529392505050565b6101208101614e2d8285805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b612fb2606083018463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614ee28285018b6145b1565b91508382036080850152614ef6828a6145b1565b915060ff881660a085015283820360c0850152614f138288613ae7565b90861660e08501528381036101008501529050614aa18185613ae7565b600060608284031215614f4257600080fd5b614f4a613c06565b8251614f5581613edc565b81526020830151614f6581613dee565b60208201526040830151614f7881613c9c565b60408201529392505050565b600060208284031215614f9657600080fd5b8151612fb281613dee565b600060208284031215614fb357600080fd5b813567ffffffffffffffff811115614fca57600080fd5b6123db84828501614291565b600060208284031215614fe857600080fd5b815167ffffffffffffffff8082111561500057600080fd5b908301906060828603121561501457600080fd5b61501c613c06565b82518281111561502b57600080fd5b61503787828601614c88565b82525060208301518281111561504c57600080fd5b61505887828601614c88565b60208301525060408301518281111561507057600080fd5b61507c87828601614c88565b60408301525095945050505050565b602081526000825160e060208401526150a8610100840182613ae7565b905067ffffffffffffffff602085015116604084015260408401516150e5606085018273ffffffffffffffffffffffffffffffffffffffff169052565b506060840151608084015260808401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160a086015261512a8383613ae7565b925060a08601519150808584030160c08601526151478383613ae7565b925060c08601519150808584030160e086015250614c238282613ae7565b6000806040838503121561517857600080fd5b505080516020909101519092909150565b60006020828403121561519b57600080fd5b8151612fb281613edc565b60008151808452602080850194506020840160005b838110156145f8578151875295820195908201906001016151bb565b67ffffffffffffffff851681526080602082015260006151fa60808301866151a6565b828103604084015261520c81866151a6565b91505082606083015295945050505050565b60006020828403121561523057600080fd5b5051919050565b67ffffffffffffffff818116838216019080821115615258576152586149c9565b5092915050565b8281526040602082015260006123db6040830184613ae7565b67ffffffffffffffff848116825283166020820152606081016123db6040830184614568565b600067ffffffffffffffff808316818103614a1157614a116149c9565b6152c58184614568565b6040602082015260006123db6040830184613ae7565b602081526000610d0a6020830184614b6b565b60008282518085526020808601955060208260051b8401016020860160005b84811015615359577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952615347838351613ae7565b9884019892509083019060010161530d565b5090979650505050505050565b602081526000610d0a60208301846152ee565b6040815261539460408201845167ffffffffffffffff169052565b600060208401516153bd606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604084015173ffffffffffffffffffffffffffffffffffffffff8116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c084015161010061542b8185018367ffffffffffffffff169052565b60e086015191506101206154568186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061014091508282860152808701519250506101a061016081818701526154866101e0870185613ae7565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06101808188870301818901526154c58686614b6b565b9550828a015194508188870301848901526154e086866152ee565b9550808a01516101c089015250505050508281036020840152614c2381856152ee565b6000815160208301517fffffffff000000000000000000000000000000000000000000000000000000008082169350600483101561554b5780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", } var EVM2EVMMultiOffRampABI = EVM2EVMMultiOffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go new file mode 100644 index 0000000000..e6023d85f1 --- /dev/null +++ b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go @@ -0,0 +1,1830 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package multi_aggregate_rate_limiter + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type ClientAny2EVMMessage struct { + MessageId [32]byte + SourceChainSelector uint64 + Sender []byte + Data []byte + DestTokenAmounts []ClientEVMTokenAmount +} + +type ClientEVM2AnyMessage struct { + Receiver []byte + Data []byte + TokenAmounts []ClientEVMTokenAmount + FeeToken common.Address + ExtraArgs []byte +} + +type ClientEVMTokenAmount struct { + Token common.Address + Amount *big.Int +} + +type MultiAggregateRateLimiterAuthorizedCallerArgs struct { + AddedCallers []common.Address + RemovedCallers []common.Address +} + +type MultiAggregateRateLimiterRateLimitToken struct { + RemoteToken common.Address + LocalToken common.Address +} + +type MultiAggregateRateLimiterRateLimiterConfigArgs struct { + RemoteChainSelector uint64 + IsOutgoingLane bool + RateLimiterConfig RateLimiterConfig +} + +type RateLimiterConfig struct { + IsEnabled bool + Capacity *big.Int + Rate *big.Int +} + +type RateLimiterTokenBucket struct { + Tokens *big.Int + LastUpdated uint32 + IsEnabled bool + Capacity *big.Int + Rate *big.Int +} + +var MultiAggregateRateLimiterMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutgoingLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimiterConfigArgs[]\",\"name\":\"rateLimiterConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpdateLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"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\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPriceRegistry\",\"type\":\"address\"}],\"name\":\"PriceRegistrySet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutgoingLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"RateLimiterConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structMultiAggregateRateLimiter.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutgoingLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimiterConfigArgs[]\",\"name\":\"rateLimiterUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applyRateLimiterConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutgoingLane\",\"type\":\"bool\"}],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"remoteTokens\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"localTokens\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPriceRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"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\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onIncomingMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"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\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"onOutgoingMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPriceRegistry\",\"type\":\"address\"}],\"name\":\"setPriceRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"remoteToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimitToken[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b506040516200330538038062003305833981016040819052620000349162000a6c565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000112565b505050620000d283620001bd60201b60201c565b620000dd8262000421565b60408051808201825282815281516000815260208082019093529181019190915262000109906200049d565b50505062000cdf565b336001600160a01b038216036200016c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156200041d576000828281518110620001e157620001e162000be0565b602090810291909101015160408101518151919250906001600160401b038116600003620002225760405163c656089560e01b815260040160405180910390fd5b60208301516000620002358383620005ec565b8054909150600160801b900463ffffffff16600003620003bb576040805160a081018252602080870180516001600160801b03908116845263ffffffff4216928401929092528751151583850152518116606083015291860151909116608082015282156200032e576001600160401b038416600090815260086020908152604091829020835160028201805493860151948601516001600160801b039283166001600160a01b031990951694909417600160801b63ffffffff90961686021760ff60a01b1916600160a01b941515949094029390931790925560608401516080850151908316921690920217600390910155620003b4565b6001600160401b0384166000908152600860209081526040918290208351815492850151938501516001600160801b039182166001600160a01b031990941693909317600160801b63ffffffff90951685021760ff60a01b1916600160a01b93151593909302929092178155606084015160808501519083169216909202176001909101555b50620003c7565b620003c781856200061f565b826001600160401b03167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b9783866040516200040492919062000bf6565b60405180910390a25050505050806001019050620001c0565b5050565b6001600160a01b03811662000449576040516342bcdf7f60e11b815260040160405180910390fd5b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527fdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df99060200160405180910390a150565b805160005b815181101562000555576000828281518110620004c357620004c362000be0565b6020026020010151905060006001600160a01b0316816001600160a01b03160362000501576040516342bcdf7f60e11b815260040160405180910390fd5b6200050e60058262000742565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101620004a2565b50602082015160005b8151811015620005e65760008282815181106200057f576200057f62000be0565b602090810291909101015190506200059960058262000759565b15620005dc576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b506001016200055e565b50505050565b6001600160401b038216600090815260086020526040812082156200061657600201905062000619565b90505b92915050565b81546000906200063d90600160801b900463ffffffff164262000c4f565b905080156200069e576001830154835462000672916001600160801b03808216928116918591600160801b9091041662000770565b83546001600160801b03919091166001600160a01b031990911617600160801b4263ffffffff16021783555b60208201518354620006bd916001600160801b0390811691166200079e565b835483511515600160a01b02600164ff0000000160801b03199091166001600160801b039283161717845560208301516040808501518316600160801b0291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19906200073590849062000c65565b60405180910390a1505050565b600062000616836001600160a01b038416620007b6565b600062000616836001600160a01b03841662000808565b6000620007958562000783848662000c99565b6200078f908762000cb3565b6200079e565b95945050505050565b6000818310620007af578162000616565b5090919050565b6000818152600183016020526040812054620007ff5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000619565b50600062000619565b60008181526001830160205260408120548015620009015760006200082f60018362000c4f565b8554909150600090620008459060019062000c4f565b9050818114620008b157600086600001828154811062000869576200086962000be0565b90600052602060002001549050808760000184815481106200088f576200088f62000be0565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080620008c557620008c562000cc9565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000619565b600091505062000619565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200094757620009476200090c565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200097857620009786200090c565b604052919050565b60006001600160401b038211156200099c576200099c6200090c565b5060051b60200190565b80518015158114620009b757600080fd5b919050565b80516001600160801b0381168114620009b757600080fd5b80516001600160a01b0381168114620009b757600080fd5b600082601f830112620009fe57600080fd5b8151602062000a1762000a118362000980565b6200094d565b8083825260208201915060208460051b87010193508684111562000a3a57600080fd5b602086015b8481101562000a615762000a5381620009d4565b835291830191830162000a3f565b509695505050505050565b6000806000606080858703121562000a8357600080fd5b84516001600160401b038082111562000a9b57600080fd5b818701915087601f83011262000ab057600080fd5b8151602062000ac362000a118362000980565b82815260a0928302850182019282820191908c85111562000ae357600080fd5b958301955b8487101562000b9b57868d038181121562000b035760008081fd5b62000b0d62000922565b8851888116811462000b1f5760008081fd5b815262000b2e898701620009a6565b8682015260408a603f198401121562000b475760008081fd5b62000b5162000922565b925062000b60818b01620009a6565b835262000b6f8b8b01620009bc565b8784015262000b8160808b01620009bc565b838201528101919091528352958601959183019162000ae8565b50985062000bad9050898201620009d4565b96505050604087015192508083111562000bc657600080fd5b505062000bd686828701620009ec565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b82151581526080810162000c3260208301848051151582526020808201516001600160801b039081169184019190915260409182015116910152565b9392505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111562000619576200061962000c39565b606081016200061982848051151582526020808201516001600160801b039081169184019190915260409182015116910152565b808202811582820484141762000619576200061962000c39565b8082018082111562000619576200061962000c39565b634e487b7160e01b600052603160045260246000fd5b6126168062000cef6000396000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c8063873504d71161008c578063a219f6e511610066578063a219f6e514610223578063f077b59214610236578063f2fde38b1461024c578063fe843cd01461025f57600080fd5b8063873504d7146101df5780638da5cb5b146101f257806391a2749a1461021057600080fd5b80632451a627116100bd5780632451a627146101af578063508ee9de146101c457806379ba5097146101d757600080fd5b806303a44ffb146100e45780630a35bcc4146100f85780630d6c107e14610170575b600080fd5b6100f66100f2366004611e32565b5050565b005b61010b610106366004611f3e565b610272565b604051610167919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60405180910390f35b60075473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610167565b6101b7610337565b6040516101679190611fba565b6100f66101d2366004611fcd565b610348565b6100f661035c565b6100f66101ed366004612075565b61045e565b60005473ffffffffffffffffffffffffffffffffffffffff1661018a565b6100f661021e36600461213f565b610676565b6100f66102313660046121d0565b610687565b61023e610761565b6040516101679291906122a0565b6100f661025a366004611fcd565b6108ba565b6100f661026d3660046122e5565b6108cb565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261032e6102aa84846108dc565b6040805160a08101825282546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff1615159383019390935260019093015480831660608301529290920416608082015261090c565b90505b92915050565b606061034360056109be565b905090565b6103506109d2565b61035981610a55565b50565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104666109d2565b60005b8251811015610546576104a383828151811061048757610487612419565b6020026020010151602001516002610b1b90919063ffffffff16565b1561053e577fcbf3cbeaed4ac1d605ed30f4af06c35acaeff2379db7f6146c9cceee83d587828382815181106104db576104db612419565b6020026020010151600001518483815181106104f9576104f9612419565b60200260200101516020015160405161053592919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60405180910390a15b600101610469565b5060005b815181101561067157600082828151811061056757610567612419565b6020026020010151602001519050600083838151811061058957610589612419565b602090810291909101015151905073ffffffffffffffffffffffffffffffffffffffff821615806105ce575073ffffffffffffffffffffffffffffffffffffffff8116155b15610605576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61061160028383610b3d565b15610667576040805173ffffffffffffffffffffffffffffffffffffffff8084168252841660208201527ffc23abf7ddbd3c02b1420dafa2355c56c1a06fbb8723862ac14d6bd74177361a910160405180910390a15b505060010161054a565b505050565b61067e6109d2565b61035981610b68565b610692600533610cfa565b6106ca576040517fd86ad9cf0000000000000000000000000000000000000000000000000000000081523360048201526024016103d9565b6080810151600090815b815181101561074a5761070e8282815181106106f2576106f2612419565b6020026020010151600001516002610d2990919063ffffffff16565b156107425761073582828151811061072857610728612419565b6020026020010151610d4b565b61073f9084612477565b92505b6001016106d4565b508115610671576106718360200151600084610e87565b60608061076e6002610e9e565b67ffffffffffffffff81111561078657610786611bbc565b6040519080825280602002602001820160405280156107af578160200160208202803683370190505b5091506107bc6002610e9e565b67ffffffffffffffff8111156107d4576107d4611bbc565b6040519080825280602002602001820160405280156107fd578160200160208202803683370190505b50905060005b61080d6002610e9e565b8110156108b557600080610822600284610ea9565b915091508085848151811061083957610839612419565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508184848151811061088657610886612419565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101525050600101610803565b509091565b6108c26109d2565b61035981610ec5565b6108d36109d2565b61035981610fba565b67ffffffffffffffff821660009081526008602052604081208215610905576002019050610331565b9050610331565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915261099a82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff164261097e919061248a565b85608001516fffffffffffffffffffffffffffffffff166112f1565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b606060006109cb83611319565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103d9565b565b73ffffffffffffffffffffffffffffffffffffffff8116610aa2576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df99060200160405180910390a150565b600061032e8373ffffffffffffffffffffffffffffffffffffffff8416611375565b6000610b608473ffffffffffffffffffffffffffffffffffffffff851684611381565b949350505050565b805160005b8151811015610c58576000828281518110610b8a57610b8a612419565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610bfa576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c056005826113a4565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101610b6d565b50602082015160005b8151811015610cf4576000828281518110610c7e57610c7e612419565b60200260200101519050610c9c8160056113c690919063ffffffff16565b15610ceb5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101610c61565b50505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561032e565b600061032e8373ffffffffffffffffffffffffffffffffffffffff84166113e8565b60075481516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000928392169063d02641a0906024016040805180830381865afa158015610dbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de3919061249d565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116600003610e595782516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016103d9565b60208301516109cb907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8316906113f4565b610671816000610e9786866108dc565b9190611431565b6000610331826117b4565b6000808080610eb886866117bf565b9097909650945050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103d9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156100f2576000828281518110610fda57610fda612419565b6020908102919091010151604081015181519192509067ffffffffffffffff8116600003611034576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020830151600061104583836108dc565b8054909150700100000000000000000000000000000000900463ffffffff16600003611293576040805160a081018252602080870180516fffffffffffffffffffffffffffffffff908116845263ffffffff4216928401929092528751151583850152518116606083015291860151909116608082015282156111ac5767ffffffffffffffff8416600090815260086020908152604091829020835160028201805493860151948601516fffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941770010000000000000000000000000000000063ffffffff9096168602177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000094151594909402939093179092556060840151608085015190831692169092021760039091015561128d565b67ffffffffffffffff84166000908152600860209081526040918290208351815492850151938501516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009094169390931770010000000000000000000000000000000063ffffffff9095168502177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000093151593909302929092178155606084015160808501519083169216909202176001909101555b5061129d565b61129d81856117ce565b8267ffffffffffffffff167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b9783866040516112d9929190612508565b60405180910390a25050505050806001019050610fbd565b600061131085611301848661254c565b61130b9087612477565b61197d565b95945050505050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561136957602002820191906000526020600020905b815481526020019060010190808311611355575b50505050509050919050565b600061032e8383611993565b6000610b60848473ffffffffffffffffffffffffffffffffffffffff85166119b0565b600061032e8373ffffffffffffffffffffffffffffffffffffffff84166119cd565b600061032e8373ffffffffffffffffffffffffffffffffffffffff8416611a1c565b600061032e8383611b0f565b6000670de0b6b3a7640000611427837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff861661254c565b61032e9190612563565b825474010000000000000000000000000000000000000000900460ff161580611458575081155b1561146257505050565b825460018401546fffffffffffffffffffffffffffffffff808316929116906000906114a890700100000000000000000000000000000000900463ffffffff164261248a565b9050801561156857818311156114ea576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546115249083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166112f1565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b8482101561161f5773ffffffffffffffffffffffffffffffffffffffff84166115c7576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016103d9565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016103d9565b848310156117325760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16906000908290611663908261248a565b61166d878a61248a565b6116779190612477565b6116819190612563565b905073ffffffffffffffffffffffffffffffffffffffff86166116da576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016103d9565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016103d9565b61173c858461248a565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600061033182611b1b565b6000808080610eb88686611b26565b81546000906117f790700100000000000000000000000000000000900463ffffffff164261248a565b90508015611899576001830154835461183f916fffffffffffffffffffffffffffffffff808216928116918591700100000000000000000000000000000000909104166112f1565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b602082015183546118bf916fffffffffffffffffffffffffffffffff908116911661197d565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061197090849061259e565b60405180910390a1505050565b600081831061198c578161032e565b5090919050565b6000818152600283016020526040812081905561032e8383611b51565b60008281526002840160205260408120829055610b608484611b5d565b6000818152600183016020526040812054611a1457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610331565b506000610331565b60008181526001830160205260408120548015611b05576000611a4060018361248a565b8554909150600090611a549060019061248a565b9050818114611ab9576000866000018281548110611a7457611a74612419565b9060005260206000200154905080876000018481548110611a9757611a97612419565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611aca57611aca6125da565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610331565b6000915050610331565b600061032e8383611b69565b600061033182611b81565b60008080611b348585611b8b565b600081815260029690960160205260409095205494959350505050565b600061032e8383611a1c565b600061032e83836119cd565b6000818152600183016020526040812054151561032e565b6000610331825490565b600061032e83836000826000018281548110611ba957611ba9612419565b9060005260206000200154905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611c0e57611c0e611bbc565b60405290565b60405160a0810167ffffffffffffffff81118282101715611c0e57611c0e611bbc565b6040516060810167ffffffffffffffff81118282101715611c0e57611c0e611bbc565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611ca157611ca1611bbc565b604052919050565b600082601f830112611cba57600080fd5b813567ffffffffffffffff811115611cd457611cd4611bbc565b611d0560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611c5a565b818152846020838601011115611d1a57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115611d5157611d51611bbc565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114611d7f57600080fd5b919050565b600082601f830112611d9557600080fd5b81356020611daa611da583611d37565b611c5a565b82815260069290921b84018101918181019086841115611dc957600080fd5b8286015b84811015611e0f5760408189031215611de65760008081fd5b611dee611beb565b611df782611d5b565b81528185013585820152835291830191604001611dcd565b509695505050505050565b803567ffffffffffffffff81168114611d7f57600080fd5b60008060408385031215611e4557600080fd5b823567ffffffffffffffff80821115611e5d57600080fd5b9084019060a08287031215611e7157600080fd5b611e79611c14565b823582811115611e8857600080fd5b611e9488828601611ca9565b825250602083013582811115611ea957600080fd5b611eb588828601611ca9565b602083015250604083013582811115611ecd57600080fd5b611ed988828601611d84565b604083015250611eeb60608401611d5b565b6060820152608083013582811115611f0257600080fd5b611f0e88828601611ca9565b6080830152509350611f2591505060208401611e1a565b90509250929050565b80358015158114611d7f57600080fd5b60008060408385031215611f5157600080fd5b611f5a83611e1a565b9150611f2560208401611f2e565b60008151808452602080850194506020840160005b83811015611faf57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611f7d565b509495945050505050565b60208152600061032e6020830184611f68565b600060208284031215611fdf57600080fd5b61032e82611d5b565b600082601f830112611ff957600080fd5b81356020612009611da583611d37565b82815260069290921b8401810191818101908684111561202857600080fd5b8286015b84811015611e0f57604081890312156120455760008081fd5b61204d611beb565b61205682611d5b565b8152612063858301611d5b565b8186015283529183019160400161202c565b6000806040838503121561208857600080fd5b823567ffffffffffffffff808211156120a057600080fd5b6120ac86838701611fe8565b935060208501359150808211156120c257600080fd5b506120cf85828601611fe8565b9150509250929050565b600082601f8301126120ea57600080fd5b813560206120fa611da583611d37565b8083825260208201915060208460051b87010193508684111561211c57600080fd5b602086015b84811015611e0f5761213281611d5b565b8352918301918301612121565b60006020828403121561215157600080fd5b813567ffffffffffffffff8082111561216957600080fd5b908301906040828603121561217d57600080fd5b612185611beb565b82358281111561219457600080fd5b6121a0878286016120d9565b8252506020830135828111156121b557600080fd5b6121c1878286016120d9565b60208301525095945050505050565b6000602082840312156121e257600080fd5b813567ffffffffffffffff808211156121fa57600080fd5b9083019060a0828603121561220e57600080fd5b612216611c14565b8235815261222660208401611e1a565b602082015260408301358281111561223d57600080fd5b61224987828601611ca9565b60408301525060608301358281111561226157600080fd5b61226d87828601611ca9565b60608301525060808301358281111561228557600080fd5b61229187828601611d84565b60808301525095945050505050565b6040815260006122b36040830185611f68565b82810360208401526113108185611f68565b80356fffffffffffffffffffffffffffffffff81168114611d7f57600080fd5b600060208083850312156122f857600080fd5b823567ffffffffffffffff81111561230f57600080fd5b8301601f8101851361232057600080fd5b803561232e611da582611d37565b81815260a0918202830184019184820191908884111561234d57600080fd5b938501935b8385101561240d578489038181121561236b5760008081fd5b612373611c37565b61237c87611e1a565b8152612389888801611f2e565b8882015260406060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0850112156123c15760008081fd5b6123c9611c37565b93506123d6828a01611f2e565b84526123e3818a016122c5565b8a850152506123f4608089016122c5565b8382015281019190915283529384019391850191612352565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561033157610331612448565b8181038181111561033157610331612448565b6000604082840312156124af57600080fd5b6124b7611beb565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146124e357600080fd5b8152602083015163ffffffff811681146124fc57600080fd5b60208201529392505050565b8215158152608081016109cb60208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b808202811582820484141761033157610331612448565b600082612599577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6060810161033182848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", +} + +var MultiAggregateRateLimiterABI = MultiAggregateRateLimiterMetaData.ABI + +var MultiAggregateRateLimiterBin = MultiAggregateRateLimiterMetaData.Bin + +func DeployMultiAggregateRateLimiter(auth *bind.TransactOpts, backend bind.ContractBackend, rateLimiterConfigs []MultiAggregateRateLimiterRateLimiterConfigArgs, priceRegistry common.Address, authorizedCallers []common.Address) (common.Address, *types.Transaction, *MultiAggregateRateLimiter, error) { + parsed, err := MultiAggregateRateLimiterMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MultiAggregateRateLimiterBin), backend, rateLimiterConfigs, priceRegistry, authorizedCallers) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &MultiAggregateRateLimiter{address: address, abi: *parsed, MultiAggregateRateLimiterCaller: MultiAggregateRateLimiterCaller{contract: contract}, MultiAggregateRateLimiterTransactor: MultiAggregateRateLimiterTransactor{contract: contract}, MultiAggregateRateLimiterFilterer: MultiAggregateRateLimiterFilterer{contract: contract}}, nil +} + +type MultiAggregateRateLimiter struct { + address common.Address + abi abi.ABI + MultiAggregateRateLimiterCaller + MultiAggregateRateLimiterTransactor + MultiAggregateRateLimiterFilterer +} + +type MultiAggregateRateLimiterCaller struct { + contract *bind.BoundContract +} + +type MultiAggregateRateLimiterTransactor struct { + contract *bind.BoundContract +} + +type MultiAggregateRateLimiterFilterer struct { + contract *bind.BoundContract +} + +type MultiAggregateRateLimiterSession struct { + Contract *MultiAggregateRateLimiter + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type MultiAggregateRateLimiterCallerSession struct { + Contract *MultiAggregateRateLimiterCaller + CallOpts bind.CallOpts +} + +type MultiAggregateRateLimiterTransactorSession struct { + Contract *MultiAggregateRateLimiterTransactor + TransactOpts bind.TransactOpts +} + +type MultiAggregateRateLimiterRaw struct { + Contract *MultiAggregateRateLimiter +} + +type MultiAggregateRateLimiterCallerRaw struct { + Contract *MultiAggregateRateLimiterCaller +} + +type MultiAggregateRateLimiterTransactorRaw struct { + Contract *MultiAggregateRateLimiterTransactor +} + +func NewMultiAggregateRateLimiter(address common.Address, backend bind.ContractBackend) (*MultiAggregateRateLimiter, error) { + abi, err := abi.JSON(strings.NewReader(MultiAggregateRateLimiterABI)) + if err != nil { + return nil, err + } + contract, err := bindMultiAggregateRateLimiter(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiter{address: address, abi: abi, MultiAggregateRateLimiterCaller: MultiAggregateRateLimiterCaller{contract: contract}, MultiAggregateRateLimiterTransactor: MultiAggregateRateLimiterTransactor{contract: contract}, MultiAggregateRateLimiterFilterer: MultiAggregateRateLimiterFilterer{contract: contract}}, nil +} + +func NewMultiAggregateRateLimiterCaller(address common.Address, caller bind.ContractCaller) (*MultiAggregateRateLimiterCaller, error) { + contract, err := bindMultiAggregateRateLimiter(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterCaller{contract: contract}, nil +} + +func NewMultiAggregateRateLimiterTransactor(address common.Address, transactor bind.ContractTransactor) (*MultiAggregateRateLimiterTransactor, error) { + contract, err := bindMultiAggregateRateLimiter(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterTransactor{contract: contract}, nil +} + +func NewMultiAggregateRateLimiterFilterer(address common.Address, filterer bind.ContractFilterer) (*MultiAggregateRateLimiterFilterer, error) { + contract, err := bindMultiAggregateRateLimiter(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterFilterer{contract: contract}, nil +} + +func bindMultiAggregateRateLimiter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := MultiAggregateRateLimiterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MultiAggregateRateLimiter.Contract.MultiAggregateRateLimiterCaller.contract.Call(opts, result, method, params...) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.MultiAggregateRateLimiterTransactor.contract.Transfer(opts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.MultiAggregateRateLimiterTransactor.contract.Transact(opts, method, params...) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _MultiAggregateRateLimiter.Contract.contract.Call(opts, result, method, params...) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.contract.Transfer(opts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.contract.Transact(opts, method, params...) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) CurrentRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64, isOutgoingLane bool) (RateLimiterTokenBucket, error) { + var out []interface{} + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "currentRateLimiterState", remoteChainSelector, isOutgoingLane) + + if err != nil { + return *new(RateLimiterTokenBucket), err + } + + out0 := *abi.ConvertType(out[0], new(RateLimiterTokenBucket)).(*RateLimiterTokenBucket) + + return out0, err + +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) CurrentRateLimiterState(remoteChainSelector uint64, isOutgoingLane bool) (RateLimiterTokenBucket, error) { + return _MultiAggregateRateLimiter.Contract.CurrentRateLimiterState(&_MultiAggregateRateLimiter.CallOpts, remoteChainSelector, isOutgoingLane) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) CurrentRateLimiterState(remoteChainSelector uint64, isOutgoingLane bool) (RateLimiterTokenBucket, error) { + return _MultiAggregateRateLimiter.Contract.CurrentRateLimiterState(&_MultiAggregateRateLimiter.CallOpts, remoteChainSelector, isOutgoingLane) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "getAllAuthorizedCallers") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) GetAllAuthorizedCallers() ([]common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetAllAuthorizedCallers(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetAllAuthorizedCallers() ([]common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetAllAuthorizedCallers(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetAllRateLimitTokens(opts *bind.CallOpts) (GetAllRateLimitTokens, + + error) { + var out []interface{} + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "getAllRateLimitTokens") + + outstruct := new(GetAllRateLimitTokens) + if err != nil { + return *outstruct, err + } + + outstruct.RemoteTokens = *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + outstruct.LocalTokens = *abi.ConvertType(out[1], new([]common.Address)).(*[]common.Address) + + return *outstruct, err + +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) GetAllRateLimitTokens() (GetAllRateLimitTokens, + + error) { + return _MultiAggregateRateLimiter.Contract.GetAllRateLimitTokens(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetAllRateLimitTokens() (GetAllRateLimitTokens, + + error) { + return _MultiAggregateRateLimiter.Contract.GetAllRateLimitTokens(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetPriceRegistry(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "getPriceRegistry") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) GetPriceRegistry() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetPriceRegistry(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetPriceRegistry() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetPriceRegistry(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) Owner() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.Owner(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) Owner() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.Owner(&_MultiAggregateRateLimiter.CallOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "acceptOwnership") +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) AcceptOwnership() (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.AcceptOwnership(&_MultiAggregateRateLimiter.TransactOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.AcceptOwnership(&_MultiAggregateRateLimiter.TransactOpts) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs MultiAggregateRateLimiterAuthorizedCallerArgs) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "applyAuthorizedCallerUpdates", authorizedCallerArgs) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs MultiAggregateRateLimiterAuthorizedCallerArgs) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.ApplyAuthorizedCallerUpdates(&_MultiAggregateRateLimiter.TransactOpts, authorizedCallerArgs) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs MultiAggregateRateLimiterAuthorizedCallerArgs) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.ApplyAuthorizedCallerUpdates(&_MultiAggregateRateLimiter.TransactOpts, authorizedCallerArgs) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) ApplyRateLimiterConfigUpdates(opts *bind.TransactOpts, rateLimiterUpdates []MultiAggregateRateLimiterRateLimiterConfigArgs) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "applyRateLimiterConfigUpdates", rateLimiterUpdates) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) ApplyRateLimiterConfigUpdates(rateLimiterUpdates []MultiAggregateRateLimiterRateLimiterConfigArgs) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.ApplyRateLimiterConfigUpdates(&_MultiAggregateRateLimiter.TransactOpts, rateLimiterUpdates) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) ApplyRateLimiterConfigUpdates(rateLimiterUpdates []MultiAggregateRateLimiterRateLimiterConfigArgs) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.ApplyRateLimiterConfigUpdates(&_MultiAggregateRateLimiter.TransactOpts, rateLimiterUpdates) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) OnIncomingMessage(opts *bind.TransactOpts, message ClientAny2EVMMessage) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "onIncomingMessage", message) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) OnIncomingMessage(message ClientAny2EVMMessage) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.OnIncomingMessage(&_MultiAggregateRateLimiter.TransactOpts, message) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) OnIncomingMessage(message ClientAny2EVMMessage) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.OnIncomingMessage(&_MultiAggregateRateLimiter.TransactOpts, message) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) OnOutgoingMessage(opts *bind.TransactOpts, message ClientEVM2AnyMessage, destChainSelector uint64) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "onOutgoingMessage", message, destChainSelector) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) OnOutgoingMessage(message ClientEVM2AnyMessage, destChainSelector uint64) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.OnOutgoingMessage(&_MultiAggregateRateLimiter.TransactOpts, message, destChainSelector) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) OnOutgoingMessage(message ClientEVM2AnyMessage, destChainSelector uint64) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.OnOutgoingMessage(&_MultiAggregateRateLimiter.TransactOpts, message, destChainSelector) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) SetPriceRegistry(opts *bind.TransactOpts, newPriceRegistry common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "setPriceRegistry", newPriceRegistry) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) SetPriceRegistry(newPriceRegistry common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.SetPriceRegistry(&_MultiAggregateRateLimiter.TransactOpts, newPriceRegistry) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) SetPriceRegistry(newPriceRegistry common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.SetPriceRegistry(&_MultiAggregateRateLimiter.TransactOpts, newPriceRegistry) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "transferOwnership", to) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.TransferOwnership(&_MultiAggregateRateLimiter.TransactOpts, to) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.TransferOwnership(&_MultiAggregateRateLimiter.TransactOpts, to) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) UpdateRateLimitTokens(opts *bind.TransactOpts, removes []MultiAggregateRateLimiterRateLimitToken, adds []MultiAggregateRateLimiterRateLimitToken) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "updateRateLimitTokens", removes, adds) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) UpdateRateLimitTokens(removes []MultiAggregateRateLimiterRateLimitToken, adds []MultiAggregateRateLimiterRateLimitToken) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.UpdateRateLimitTokens(&_MultiAggregateRateLimiter.TransactOpts, removes, adds) +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) UpdateRateLimitTokens(removes []MultiAggregateRateLimiterRateLimitToken, adds []MultiAggregateRateLimiterRateLimitToken) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.UpdateRateLimitTokens(&_MultiAggregateRateLimiter.TransactOpts, removes, adds) +} + +type MultiAggregateRateLimiterAuthorizedCallerAddedIterator struct { + Event *MultiAggregateRateLimiterAuthorizedCallerAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterAuthorizedCallerAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterAuthorizedCallerAdded) + 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(MultiAggregateRateLimiterAuthorizedCallerAdded) + 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 *MultiAggregateRateLimiterAuthorizedCallerAddedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterAuthorizedCallerAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterAuthorizedCallerAdded struct { + Caller common.Address + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*MultiAggregateRateLimiterAuthorizedCallerAddedIterator, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "AuthorizedCallerAdded") + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterAuthorizedCallerAddedIterator{contract: _MultiAggregateRateLimiter.contract, event: "AuthorizedCallerAdded", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterAuthorizedCallerAdded) (event.Subscription, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "AuthorizedCallerAdded") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterAuthorizedCallerAdded) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "AuthorizedCallerAdded", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseAuthorizedCallerAdded(log types.Log) (*MultiAggregateRateLimiterAuthorizedCallerAdded, error) { + event := new(MultiAggregateRateLimiterAuthorizedCallerAdded) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "AuthorizedCallerAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterAuthorizedCallerRemovedIterator struct { + Event *MultiAggregateRateLimiterAuthorizedCallerRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterAuthorizedCallerRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterAuthorizedCallerRemoved) + 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(MultiAggregateRateLimiterAuthorizedCallerRemoved) + 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 *MultiAggregateRateLimiterAuthorizedCallerRemovedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterAuthorizedCallerRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterAuthorizedCallerRemoved struct { + Caller common.Address + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*MultiAggregateRateLimiterAuthorizedCallerRemovedIterator, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "AuthorizedCallerRemoved") + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterAuthorizedCallerRemovedIterator{contract: _MultiAggregateRateLimiter.contract, event: "AuthorizedCallerRemoved", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterAuthorizedCallerRemoved) (event.Subscription, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "AuthorizedCallerRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterAuthorizedCallerRemoved) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "AuthorizedCallerRemoved", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseAuthorizedCallerRemoved(log types.Log) (*MultiAggregateRateLimiterAuthorizedCallerRemoved, error) { + event := new(MultiAggregateRateLimiterAuthorizedCallerRemoved) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "AuthorizedCallerRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterConfigChangedIterator struct { + Event *MultiAggregateRateLimiterConfigChanged + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterConfigChangedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterConfigChanged) + 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(MultiAggregateRateLimiterConfigChanged) + 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 *MultiAggregateRateLimiterConfigChangedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterConfigChangedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterConfigChanged struct { + Config RateLimiterConfig + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterConfigChanged(opts *bind.FilterOpts) (*MultiAggregateRateLimiterConfigChangedIterator, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "ConfigChanged") + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterConfigChangedIterator{contract: _MultiAggregateRateLimiter.contract, event: "ConfigChanged", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterConfigChanged) (event.Subscription, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "ConfigChanged") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterConfigChanged) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "ConfigChanged", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseConfigChanged(log types.Log) (*MultiAggregateRateLimiterConfigChanged, error) { + event := new(MultiAggregateRateLimiterConfigChanged) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "ConfigChanged", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterOwnershipTransferRequestedIterator struct { + Event *MultiAggregateRateLimiterOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) + 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(MultiAggregateRateLimiterOwnershipTransferRequested) + 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 *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, 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 := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterOwnershipTransferRequestedIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, 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 := _MultiAggregateRateLimiter.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(MultiAggregateRateLimiterOwnershipTransferRequested) + if err := _MultiAggregateRateLimiter.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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferRequested(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferRequested, error) { + event := new(MultiAggregateRateLimiterOwnershipTransferRequested) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterOwnershipTransferredIterator struct { + Event *MultiAggregateRateLimiterOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) + 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(MultiAggregateRateLimiterOwnershipTransferred) + 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 *MultiAggregateRateLimiterOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferredIterator, 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 := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterOwnershipTransferredIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferred, 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 := _MultiAggregateRateLimiter.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(MultiAggregateRateLimiterOwnershipTransferred) + if err := _MultiAggregateRateLimiter.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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) { + event := new(MultiAggregateRateLimiterOwnershipTransferred) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterPriceRegistrySetIterator struct { + Event *MultiAggregateRateLimiterPriceRegistrySet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterPriceRegistrySet) + 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(MultiAggregateRateLimiterPriceRegistrySet) + 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 *MultiAggregateRateLimiterPriceRegistrySetIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterPriceRegistrySet struct { + NewPriceRegistry common.Address + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterPriceRegistrySet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterPriceRegistrySetIterator, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "PriceRegistrySet") + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterPriceRegistrySetIterator{contract: _MultiAggregateRateLimiter.contract, event: "PriceRegistrySet", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchPriceRegistrySet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterPriceRegistrySet) (event.Subscription, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "PriceRegistrySet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterPriceRegistrySet) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "PriceRegistrySet", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParsePriceRegistrySet(log types.Log) (*MultiAggregateRateLimiterPriceRegistrySet, error) { + event := new(MultiAggregateRateLimiterPriceRegistrySet) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "PriceRegistrySet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator struct { + Event *MultiAggregateRateLimiterRateLimiterConfigUpdated + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterRateLimiterConfigUpdated) + 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(MultiAggregateRateLimiterRateLimiterConfigUpdated) + 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 *MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterRateLimiterConfigUpdated struct { + RemoteChainSelector uint64 + IsOutgoingLane bool + Config RateLimiterConfig + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterRateLimiterConfigUpdated(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "RateLimiterConfigUpdated", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator{contract: _MultiAggregateRateLimiter.contract, event: "RateLimiterConfigUpdated", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchRateLimiterConfigUpdated(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterRateLimiterConfigUpdated, remoteChainSelector []uint64) (event.Subscription, error) { + + var remoteChainSelectorRule []interface{} + for _, remoteChainSelectorItem := range remoteChainSelector { + remoteChainSelectorRule = append(remoteChainSelectorRule, remoteChainSelectorItem) + } + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "RateLimiterConfigUpdated", remoteChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterRateLimiterConfigUpdated) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "RateLimiterConfigUpdated", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseRateLimiterConfigUpdated(log types.Log) (*MultiAggregateRateLimiterRateLimiterConfigUpdated, error) { + event := new(MultiAggregateRateLimiterRateLimiterConfigUpdated) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "RateLimiterConfigUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator struct { + Event *MultiAggregateRateLimiterTokenAggregateRateLimitAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterTokenAggregateRateLimitAdded) + 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(MultiAggregateRateLimiterTokenAggregateRateLimitAdded) + 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 *MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterTokenAggregateRateLimitAdded struct { + RemoteToken common.Address + LocalToken common.Address + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterTokenAggregateRateLimitAdded(opts *bind.FilterOpts) (*MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "TokenAggregateRateLimitAdded") + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator{contract: _MultiAggregateRateLimiter.contract, event: "TokenAggregateRateLimitAdded", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchTokenAggregateRateLimitAdded(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterTokenAggregateRateLimitAdded) (event.Subscription, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "TokenAggregateRateLimitAdded") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterTokenAggregateRateLimitAdded) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "TokenAggregateRateLimitAdded", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseTokenAggregateRateLimitAdded(log types.Log) (*MultiAggregateRateLimiterTokenAggregateRateLimitAdded, error) { + event := new(MultiAggregateRateLimiterTokenAggregateRateLimitAdded) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "TokenAggregateRateLimitAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterTokenAggregateRateLimitRemovedIterator struct { + Event *MultiAggregateRateLimiterTokenAggregateRateLimitRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterTokenAggregateRateLimitRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) + 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(MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) + 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 *MultiAggregateRateLimiterTokenAggregateRateLimitRemovedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterTokenAggregateRateLimitRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterTokenAggregateRateLimitRemoved struct { + RemoteToken common.Address + LocalToken common.Address + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterTokenAggregateRateLimitRemoved(opts *bind.FilterOpts) (*MultiAggregateRateLimiterTokenAggregateRateLimitRemovedIterator, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "TokenAggregateRateLimitRemoved") + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterTokenAggregateRateLimitRemovedIterator{contract: _MultiAggregateRateLimiter.contract, event: "TokenAggregateRateLimitRemoved", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchTokenAggregateRateLimitRemoved(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) (event.Subscription, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "TokenAggregateRateLimitRemoved") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "TokenAggregateRateLimitRemoved", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseTokenAggregateRateLimitRemoved(log types.Log) (*MultiAggregateRateLimiterTokenAggregateRateLimitRemoved, error) { + event := new(MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "TokenAggregateRateLimitRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type MultiAggregateRateLimiterTokensConsumedIterator struct { + Event *MultiAggregateRateLimiterTokensConsumed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *MultiAggregateRateLimiterTokensConsumedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(MultiAggregateRateLimiterTokensConsumed) + 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(MultiAggregateRateLimiterTokensConsumed) + 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 *MultiAggregateRateLimiterTokensConsumedIterator) Error() error { + return it.fail +} + +func (it *MultiAggregateRateLimiterTokensConsumedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type MultiAggregateRateLimiterTokensConsumed struct { + Tokens *big.Int + Raw types.Log +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterTokensConsumed(opts *bind.FilterOpts) (*MultiAggregateRateLimiterTokensConsumedIterator, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "TokensConsumed") + if err != nil { + return nil, err + } + return &MultiAggregateRateLimiterTokensConsumedIterator{contract: _MultiAggregateRateLimiter.contract, event: "TokensConsumed", logs: logs, sub: sub}, nil +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterTokensConsumed) (event.Subscription, error) { + + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "TokensConsumed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(MultiAggregateRateLimiterTokensConsumed) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "TokensConsumed", 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 (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseTokensConsumed(log types.Log) (*MultiAggregateRateLimiterTokensConsumed, error) { + event := new(MultiAggregateRateLimiterTokensConsumed) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "TokensConsumed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetAllRateLimitTokens struct { + RemoteTokens []common.Address + LocalTokens []common.Address +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiter) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _MultiAggregateRateLimiter.abi.Events["AuthorizedCallerAdded"].ID: + return _MultiAggregateRateLimiter.ParseAuthorizedCallerAdded(log) + case _MultiAggregateRateLimiter.abi.Events["AuthorizedCallerRemoved"].ID: + return _MultiAggregateRateLimiter.ParseAuthorizedCallerRemoved(log) + case _MultiAggregateRateLimiter.abi.Events["ConfigChanged"].ID: + return _MultiAggregateRateLimiter.ParseConfigChanged(log) + case _MultiAggregateRateLimiter.abi.Events["OwnershipTransferRequested"].ID: + return _MultiAggregateRateLimiter.ParseOwnershipTransferRequested(log) + case _MultiAggregateRateLimiter.abi.Events["OwnershipTransferred"].ID: + return _MultiAggregateRateLimiter.ParseOwnershipTransferred(log) + case _MultiAggregateRateLimiter.abi.Events["PriceRegistrySet"].ID: + return _MultiAggregateRateLimiter.ParsePriceRegistrySet(log) + case _MultiAggregateRateLimiter.abi.Events["RateLimiterConfigUpdated"].ID: + return _MultiAggregateRateLimiter.ParseRateLimiterConfigUpdated(log) + case _MultiAggregateRateLimiter.abi.Events["TokenAggregateRateLimitAdded"].ID: + return _MultiAggregateRateLimiter.ParseTokenAggregateRateLimitAdded(log) + case _MultiAggregateRateLimiter.abi.Events["TokenAggregateRateLimitRemoved"].ID: + return _MultiAggregateRateLimiter.ParseTokenAggregateRateLimitRemoved(log) + case _MultiAggregateRateLimiter.abi.Events["TokensConsumed"].ID: + return _MultiAggregateRateLimiter.ParseTokensConsumed(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (MultiAggregateRateLimiterAuthorizedCallerAdded) Topic() common.Hash { + return common.HexToHash("0xeb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef") +} + +func (MultiAggregateRateLimiterAuthorizedCallerRemoved) Topic() common.Hash { + return common.HexToHash("0xc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda77580") +} + +func (MultiAggregateRateLimiterConfigChanged) Topic() common.Hash { + return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") +} + +func (MultiAggregateRateLimiterOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (MultiAggregateRateLimiterOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (MultiAggregateRateLimiterPriceRegistrySet) Topic() common.Hash { + return common.HexToHash("0xdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df9") +} + +func (MultiAggregateRateLimiterRateLimiterConfigUpdated) Topic() common.Hash { + return common.HexToHash("0xf14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b97") +} + +func (MultiAggregateRateLimiterTokenAggregateRateLimitAdded) Topic() common.Hash { + return common.HexToHash("0xfc23abf7ddbd3c02b1420dafa2355c56c1a06fbb8723862ac14d6bd74177361a") +} + +func (MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) Topic() common.Hash { + return common.HexToHash("0xcbf3cbeaed4ac1d605ed30f4af06c35acaeff2379db7f6146c9cceee83d58782") +} + +func (MultiAggregateRateLimiterTokensConsumed) Topic() common.Hash { + return common.HexToHash("0x1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a") +} + +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiter) Address() common.Address { + return _MultiAggregateRateLimiter.address +} + +type MultiAggregateRateLimiterInterface interface { + CurrentRateLimiterState(opts *bind.CallOpts, remoteChainSelector uint64, isOutgoingLane bool) (RateLimiterTokenBucket, error) + + GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) + + GetAllRateLimitTokens(opts *bind.CallOpts) (GetAllRateLimitTokens, + + error) + + GetPriceRegistry(opts *bind.CallOpts) (common.Address, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs MultiAggregateRateLimiterAuthorizedCallerArgs) (*types.Transaction, error) + + ApplyRateLimiterConfigUpdates(opts *bind.TransactOpts, rateLimiterUpdates []MultiAggregateRateLimiterRateLimiterConfigArgs) (*types.Transaction, error) + + OnIncomingMessage(opts *bind.TransactOpts, message ClientAny2EVMMessage) (*types.Transaction, error) + + OnOutgoingMessage(opts *bind.TransactOpts, message ClientEVM2AnyMessage, destChainSelector uint64) (*types.Transaction, error) + + SetPriceRegistry(opts *bind.TransactOpts, newPriceRegistry common.Address) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + UpdateRateLimitTokens(opts *bind.TransactOpts, removes []MultiAggregateRateLimiterRateLimitToken, adds []MultiAggregateRateLimiterRateLimitToken) (*types.Transaction, error) + + FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*MultiAggregateRateLimiterAuthorizedCallerAddedIterator, error) + + WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterAuthorizedCallerAdded) (event.Subscription, error) + + ParseAuthorizedCallerAdded(log types.Log) (*MultiAggregateRateLimiterAuthorizedCallerAdded, error) + + FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*MultiAggregateRateLimiterAuthorizedCallerRemovedIterator, error) + + WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterAuthorizedCallerRemoved) (event.Subscription, error) + + ParseAuthorizedCallerRemoved(log types.Log) (*MultiAggregateRateLimiterAuthorizedCallerRemoved, error) + + FilterConfigChanged(opts *bind.FilterOpts) (*MultiAggregateRateLimiterConfigChangedIterator, error) + + WatchConfigChanged(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterConfigChanged) (event.Subscription, error) + + ParseConfigChanged(log types.Log) (*MultiAggregateRateLimiterConfigChanged, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) + + FilterPriceRegistrySet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterPriceRegistrySetIterator, error) + + WatchPriceRegistrySet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterPriceRegistrySet) (event.Subscription, error) + + ParsePriceRegistrySet(log types.Log) (*MultiAggregateRateLimiterPriceRegistrySet, error) + + FilterRateLimiterConfigUpdated(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator, error) + + WatchRateLimiterConfigUpdated(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterRateLimiterConfigUpdated, remoteChainSelector []uint64) (event.Subscription, error) + + ParseRateLimiterConfigUpdated(log types.Log) (*MultiAggregateRateLimiterRateLimiterConfigUpdated, error) + + FilterTokenAggregateRateLimitAdded(opts *bind.FilterOpts) (*MultiAggregateRateLimiterTokenAggregateRateLimitAddedIterator, error) + + WatchTokenAggregateRateLimitAdded(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterTokenAggregateRateLimitAdded) (event.Subscription, error) + + ParseTokenAggregateRateLimitAdded(log types.Log) (*MultiAggregateRateLimiterTokenAggregateRateLimitAdded, error) + + FilterTokenAggregateRateLimitRemoved(opts *bind.FilterOpts) (*MultiAggregateRateLimiterTokenAggregateRateLimitRemovedIterator, error) + + WatchTokenAggregateRateLimitRemoved(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterTokenAggregateRateLimitRemoved) (event.Subscription, error) + + ParseTokenAggregateRateLimitRemoved(log types.Log) (*MultiAggregateRateLimiterTokenAggregateRateLimitRemoved, error) + + FilterTokensConsumed(opts *bind.FilterOpts) (*MultiAggregateRateLimiterTokensConsumedIterator, error) + + WatchTokensConsumed(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterTokensConsumed) (event.Subscription, error) + + ParseTokensConsumed(log types.Log) (*MultiAggregateRateLimiterTokensConsumed, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} 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 874c529e45..943059def3 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 @@ -9,7 +9,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 bd56fec69d252bd9b87b5dd647e2eca937cf0b92674c824aa5f17427eba1c657 custom_token_pool: ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.abi ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.bin 488bd34d63be7b731f4fbdf0cd353f7e4fbee990cfa4db26be91973297d3f803 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin b398a1906f73f9ce537954611f995447ef1ac810532c6866cecf0bd19b9c357c -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin b21c98fa8a88195af432661f96318964b26359438caddfee98f1eee537bae9c4 +evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 20b1d8e51d01d512ecacca05eccdd0b8bd76a7cff132702a7f26d638fab53f0b evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin c4f9946b23a0887d8744e203a6d9a50252fc0ed949348bd52f2b810e14940081 evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin 0daedb073a1b3563eb014f3363e0c796ade734ffbb217562f47101fdf0837c4a evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin ccd73e2c7e07bac0805da8fa09bcd4434ddf69296e6cb75e4c6933276ffac129 @@ -20,6 +20,7 @@ mock_arm_contract: ../../../contracts/solc/v0.8.24/MockRMN/MockRMN.abi ../../../ mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin e0cf17a38b438239fc6294ddca88f86b6c39e4542aefd9815b2d92987191b8bd mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin c4f34dcb1bd9aca70d6fff57001430015f3f35106cbd16fff246a5c3a5e4d7d3 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 +multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 012c23086123d4d295147204ef56eede4e120d0da948850fae9d66b97ecd92bb ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin f20a959d836ee223b56cd5f463d67c5211630bdd369f67862fb0653347dabb50 price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin 68d1a92a6b7d6a864ef23723984723848d90bbdf58e49391c6767fe2bfb6c5a7 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 1cba0f3fa69aedd8798d3c99620850a4055f52452c1f91d67b5c0caa9c181a6e diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index abcae1efeb..1c68ebe572 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -26,6 +26,7 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin EVM2EVMMultiOnRamp evm_2_evm_multi_onramp //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin EVM2EVMOffRamp evm_2_evm_offramp //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin EVM2EVMMultiOffRamp evm_2_evm_multi_offramp +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin Router router //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin PriceRegistry price_registry From 4bb71ef6361dd0a579e89fb3bddcb78ad7c65ae7 Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 29 May 2024 13:51:01 +0200 Subject: [PATCH 22/23] chore: re-gen snapshots and wrappers --- contracts/gas-snapshots/ccip.gas-snapshot | 48 +++++++++---------- ...rapper-dependency-versions-do-not-edit.txt | 12 +---- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 18336dbaea..1b1c5d1481 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -65,7 +65,7 @@ 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: 1058957) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1067897) EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 409655) EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 145631) EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12398) @@ -80,24 +80,22 @@ EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_R EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 286885) EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 232312) EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 157565) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 185248) -EVM2EVMMultiOffRamp_batchExecute:test_Paused_Revert() (gas: 125195) +EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 185226) EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 142358) -EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 490499) -EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10447) +EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 494535) +EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10418) EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 17112) EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5028941) EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 97599) EVM2EVMMultiOffRamp_execute:test_DisabledSourceChain_Revert() (gas: 37356) EVM2EVMMultiOffRamp_execute:test_EmptyReport_Revert() (gas: 21645) EVM2EVMMultiOffRamp_execute:test_InvalidMessageId_Revert() (gas: 41668) -EVM2EVMMultiOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 424633) +EVM2EVMMultiOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 427834) EVM2EVMMultiOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 51679) EVM2EVMMultiOffRamp_execute:test_MessageTooLarge_Revert() (gas: 160305) EVM2EVMMultiOffRamp_execute:test_MismatchingOnRampAddress_Revert() (gas: 44471) EVM2EVMMultiOffRamp_execute:test_MismatchingSourceChainSelector_Revert() (gas: 41560) EVM2EVMMultiOffRamp_execute:test_NonExistingSourceChain_Revert() (gas: 37615) -EVM2EVMMultiOffRamp_execute:test_Paused_Revert() (gas: 123154) EVM2EVMMultiOffRamp_execute:test_ReceiverError_Success() (gas: 176721) EVM2EVMMultiOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 190038) EVM2EVMMultiOffRamp_execute:test_RootNotCommitted_Revert() (gas: 46401) @@ -106,25 +104,25 @@ EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokensOtherChain_Success() (gas: EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 188797) EVM2EVMMultiOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 257520) EVM2EVMMultiOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 125326) -EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 366689) +EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 368707) EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 62113) EVM2EVMMultiOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 59579) -EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 499083) -EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 436654) +EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 503119) +EVM2EVMMultiOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 440690) EVM2EVMMultiOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35734) -EVM2EVMMultiOffRamp_execute:test_UnhealthySingleChainCurse_Revert() (gas: 488746) -EVM2EVMMultiOffRamp_execute:test_Unhealthy_Revert() (gas: 486353) +EVM2EVMMultiOffRamp_execute:test_UnhealthySingleChainCurse_Revert() (gas: 492782) +EVM2EVMMultiOffRamp_execute:test_Unhealthy_Revert() (gas: 490389) EVM2EVMMultiOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 71668) -EVM2EVMMultiOffRamp_execute:test_WithCurseOnAnotherSourceChain_Success() (gas: 453588) +EVM2EVMMultiOffRamp_execute:test_WithCurseOnAnotherSourceChain_Success() (gas: 457623) EVM2EVMMultiOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 155597) EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20641) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 229960) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 231978) EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20268) -EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 181672) +EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 192764) EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50926) EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 50414) EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 158010) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 264324) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 266342) EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 156820) EVM2EVMMultiOffRamp_execute_upgrade:test_NoPrevOffRampForChain_Success() (gas: 247688) EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 247477) @@ -147,18 +145,18 @@ EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (ga EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithMultiReportGasOverride_Success() (gas: 654429) EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecWithPartialMessages_Success() (gas: 295713) EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 208013) -EVM2EVMMultiOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2318022) +EVM2EVMMultiOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2319064) EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnOnRampAddress_Success() (gas: 10983) EVM2EVMMultiOffRamp_metadataHash:test_MetadataHashChangesOnSourceChain_Success() (gas: 11036) EVM2EVMMultiOffRamp_metadataHash:test_MetadataHash_Success() (gas: 9169) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 151908) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 156371) EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAContract_Reverts() (gas: 32046) EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 28422) EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 64901) EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 50943) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 70763) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 167094) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 121533) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 72429) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 169094) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 122485) EVM2EVMMultiOffRamp_report:test_IncorrectArrayType_Revert() (gas: 9982) EVM2EVMMultiOffRamp_report:test_LargeBatch_Success() (gas: 1494774) EVM2EVMMultiOffRamp_report:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 385109) @@ -170,10 +168,10 @@ EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 38184) EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38497) EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 117401) EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 139471) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 197414) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 206005) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 282919) -EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 262652) +EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 208506) +EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 217097) +EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 284913) +EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 264670) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16208) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_InvalidDestChainConfigNewPrevOnRampOnExistingChain_Revert() (gas: 29352) EVM2EVMMultiOnRamp_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput() (gas: 12405) 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 1a54df9135..ad76a6bd41 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 @@ -7,16 +7,10 @@ burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoo burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 10745e6a772b9c9efe291577daba0ba6d4e5ad22a5597152e735041e7b26d958 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin fabb5ac1286a94b7706c5d638c3a80f7b5a951c7525867d6754b018ea60c082f commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin bd56fec69d252bd9b87b5dd647e2eca937cf0b92674c824aa5f17427eba1c657 -<<<<<<< HEAD custom_token_pool: ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.abi ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.bin 488bd34d63be7b731f4fbdf0cd353f7e4fbee990cfa4db26be91973297d3f803 -ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin b398a1906f73f9ce537954611f995447ef1ac810532c6866cecf0bd19b9c357c -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 20b1d8e51d01d512ecacca05eccdd0b8bd76a7cff132702a7f26d638fab53f0b -evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin c4f9946b23a0887d8744e203a6d9a50252fc0ed949348bd52f2b810e14940081 -======= ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin f72f9f4562a6f788f9f59197f34bd603476fe8c2555c9eebba72e9d9b445cbcc -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 13b1aeccfd45e2725b9f90281034405b90f3b064621ca1d26267674c454e77a2 +evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 20b1d8e51d01d512ecacca05eccdd0b8bd76a7cff132702a7f26d638fab53f0b evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 86bb3fe6408b720e626affff65df424e587baae48396e3e0d3e3e3725343ab95 ->>>>>>> ccip-develop evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin 0daedb073a1b3563eb014f3363e0c796ade734ffbb217562f47101fdf0837c4a evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin d8a663d8071b93bf09367f406c532fa87f2a4b156e8db250f922ca979cb1fab9 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin 40bbe8c38c4f0b4aebe6f62a2c324209986e4a559b1ea8b0381f8d2586b13f29 @@ -26,12 +20,8 @@ mock_arm_contract: ../../../contracts/solc/v0.8.24/MockRMN/MockRMN.abi ../../../ mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin e0cf17a38b438239fc6294ddca88f86b6c39e4542aefd9815b2d92987191b8bd mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin c4f34dcb1bd9aca70d6fff57001430015f3f35106cbd16fff246a5c3a5e4d7d3 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 -<<<<<<< HEAD multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 012c23086123d4d295147204ef56eede4e120d0da948850fae9d66b97ecd92bb -ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin f20a959d836ee223b56cd5f463d67c5211630bdd369f67862fb0653347dabb50 -======= ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 1588313bb5e781d181a825247d30828f59007700f36b4b9b00391592b06ff4b4 ->>>>>>> ccip-develop price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin 68d1a92a6b7d6a864ef23723984723848d90bbdf58e49391c6767fe2bfb6c5a7 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 1cba0f3fa69aedd8798d3c99620850a4055f52452c1f91d67b5c0caa9c181a6e router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 42576577e81beea9a069bd9229caaa9a71227fbaef3871a1a2e69fd218216290 From 49d28b4dbc09214142571fdecc28550d23204a3c Mon Sep 17 00:00:00 2001 From: Evaldas Latoskinas Date: Wed, 29 May 2024 14:26:45 +0200 Subject: [PATCH 23/23] fix: non-ccip receiver message validation for offramp --- contracts/gas-snapshots/ccip.gas-snapshot | 15 ++++++----- .../v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol | 21 ++++++++------- .../test/helpers/MessageInterceptorHelper.sol | 3 ++- .../test/offRamp/EVM2EVMMultiOffRamp.t.sol | 26 +++++++++++++++++++ .../evm_2_evm_multi_offramp.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 6 files changed, 49 insertions(+), 20 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 1b1c5d1481..8921b7ef54 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -85,7 +85,7 @@ EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 142358) EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 494535) EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10418) EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 17112) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5028941) +EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5029341) EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 97599) EVM2EVMMultiOffRamp_execute:test_DisabledSourceChain_Revert() (gas: 37356) EVM2EVMMultiOffRamp_execute:test_EmptyReport_Revert() (gas: 21645) @@ -102,7 +102,7 @@ EVM2EVMMultiOffRamp_execute:test_RootNotCommitted_Revert() (gas: 46401) EVM2EVMMultiOffRamp_execute:test_RouterYULCall_Revert() (gas: 412264) EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokensOtherChain_Success() (gas: 241243) EVM2EVMMultiOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 188797) -EVM2EVMMultiOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 257520) +EVM2EVMMultiOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 260122) EVM2EVMMultiOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 125326) EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 368707) EVM2EVMMultiOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 62113) @@ -116,12 +116,13 @@ EVM2EVMMultiOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 71668) EVM2EVMMultiOffRamp_execute:test_WithCurseOnAnotherSourceChain_Success() (gas: 457623) EVM2EVMMultiOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 155597) EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20641) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 231978) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20268) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 232586) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 22870) EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 192764) EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 50926) EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 50414) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 158010) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 296954) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 152763) EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 266342) EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 156820) EVM2EVMMultiOffRamp_execute_upgrade:test_NoPrevOffRampForChain_Success() (gas: 247688) @@ -130,7 +131,7 @@ EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedNonceStartsAtV1Nonce_Success() EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 279986) EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249085) EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237145) -EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedWithMultiRamp_Revert() (gas: 5057060) +EVM2EVMMultiOffRamp_execute_upgrade:test_UpgradedWithMultiRamp_Revert() (gas: 5057460) EVM2EVMMultiOffRamp_execute_upgrade:test_Upgraded_Success() (gas: 142645) EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3591010) EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118288) @@ -159,7 +160,7 @@ EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 122485) EVM2EVMMultiOffRamp_report:test_IncorrectArrayType_Revert() (gas: 9982) EVM2EVMMultiOffRamp_report:test_LargeBatch_Success() (gas: 1494774) -EVM2EVMMultiOffRamp_report:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 385109) +EVM2EVMMultiOffRamp_report:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 377115) EVM2EVMMultiOffRamp_report:test_MultipleReports_Success() (gas: 232704) EVM2EVMMultiOffRamp_report:test_NonArray_Revert() (gas: 22752) EVM2EVMMultiOffRamp_report:test_SingleReport_Success() (gas: 140039) diff --git a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol index d7d088bb16..68685811da 100644 --- a/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/EVM2EVMMultiOffRamp.sol @@ -536,6 +536,17 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN offchainTokenData ); } + + Client.Any2EVMMessage memory any2EvmMessage = Internal._toAny2EVMMessage(message, destTokenAmounts); + + address messageValidator = s_dynamicConfig.messageValidator; + if (messageValidator != address(0)) { + try IMessageInterceptor(messageValidator).onIncomingMessage(any2EvmMessage) {} + catch (bytes memory err) { + revert IMessageInterceptor.MessageValidationError(err); + } + } + // There are three cases in which we skip calling the receiver: // 1. If the message data is empty AND the gas limit is 0. // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract @@ -550,16 +561,6 @@ contract EVM2EVMMultiOffRamp is IAny2EVMMultiOffRamp, ITypeAndVersion, OCR2BaseN || !message.receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) ) return; - Client.Any2EVMMessage memory any2EvmMessage = Internal._toAny2EVMMessage(message, destTokenAmounts); - - address messageValidator = s_dynamicConfig.messageValidator; - if (messageValidator != address(0)) { - try IMessageInterceptor(messageValidator).onIncomingMessage(any2EvmMessage) {} - catch (bytes memory err) { - revert IMessageInterceptor.MessageValidationError(err); - } - } - (bool success, bytes memory returnData,) = IRouter(s_dynamicConfig.router).routeMessage( any2EvmMessage, Internal.GAS_FOR_CALL_EXACT_CHECK, message.gasLimit, message.receiver ); diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol index e6ea39c505..ac7f8004ca 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageInterceptorHelper.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import "../../interfaces/IMessageInterceptor.sol"; +import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; +import {Client} from "../../libraries/Client.sol"; contract MessageInterceptorHelper is IMessageInterceptor { error IncomingMessageValidationError(bytes errorReason); diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol index d8468fdaf9..f5d405570e 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMMultiOffRamp.t.sol @@ -1209,6 +1209,32 @@ contract EVM2EVMMultiOffRamp_executeSingleMessage is EVM2EVMMultiOffRampSetup { ); s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); } + + function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { + vm.stopPrank(); + vm.startPrank(OWNER); + _enableMessageValidator(); + vm.startPrank(address(s_offRamp)); + + Internal.EVM2EVMMessage memory message = + _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + // Setup the receiver to a non-CCIP Receiver, which will skip the Router call (but should still perform the validation) + MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); + message.receiver = address(newReceiver); + message.messageId = Internal._hash(message, s_offRamp.metadataHash(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1)); + + s_messageValidator.setMessageIdValidationState(message.messageId, true); + vm.expectRevert( + abi.encodeWithSelector( + IMessageInterceptor.MessageValidationError.selector, + abi.encodeWithSelector( + MessageInterceptorHelper.IncomingMessageValidationError.selector, bytes("Invalid message") + ) + ) + ); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + } } contract EVM2EVMMultiOffRamp_batchExecute is EVM2EVMMultiOffRampSetup { diff --git a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go index fb853b2c0b..dbe2b09d99 100644 --- a/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go +++ b/core/gethwrappers/ccip/generated/evm_2_evm_multi_offramp/evm_2_evm_multi_offramp.go @@ -98,7 +98,7 @@ type InternalExecutionReportSingleChain struct { var EVM2EVMMultiOffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyExecuted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"message\",\"type\":\"string\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"name\":\"InvalidMessageId\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"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\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"error\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedIncorrectNonce\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SkippedSenderWithPreviousRampMessageInflight\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"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\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"getSenderNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"prevOffRamp\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"onRamp\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"metadataHash\",\"type\":\"bytes32\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"commitStore\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"}],\"internalType\":\"structEVM2EVMMultiOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitters\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"strict\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"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\":\"bytes[]\",\"name\":\"sourceTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.EVM2EVMMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setOCR2Config\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b5060405162005e3038038062005e30833981016040819052620000359162000678565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200012c565b5050466080525081516001600160a01b0316620000ef576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160a01b0390811660a05260208301516001600160401b031660c05260408301511660e0526200012481620001d7565b505062000850565b336001600160a01b03821603620001865760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156200053a576000828281518110620001fb57620001fb620007e3565b60200260200101519050600081600001519050806001600160401b0316600003620002455760405163c39a620560e01b81526001600160401b038216600482015260240162000083565b60608201516001600160a01b031662000271576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260096020526040902060018101546001600160a01b0316620004395760a0516040516374eb454760e11b81526001600160401b03841660048201526000916001600160a01b03169063e9d68a8e90602401606060405180830381865afa158015620002ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003159190620007f9565b905083606001516001600160a01b031681604001516001600160a01b03161415806200034d575060208101516001600160401b031615155b15620003785760405163c39a620560e01b81526001600160401b038416600482015260240162000083565b620003af8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36200053e60201b60201c565b600283015560608401516001830180546001600160a01b0319166001600160a01b039283161790556040808601518454610100600160a81b0319166101009190931602919091178355516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150620004a0565b606083015160018201546001600160a01b0390811691161415806200047557506040830151815461010090046001600160a01b03908116911614155b15620004a05760405163c39a620560e01b81526001600160401b038316600482015260240162000083565b6020830151815490151560ff199091161781556040516001600160401b038316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af07927849062000523908490815460ff81161515825260081c6001600160a01b0390811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050620001da565b5050565b60c05160408051602081018490526001600160401b0380871692820192909252911660608201526001600160a01b038316608082015260009060a0016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620005d457620005d462000599565b60405290565b604051608081016001600160401b0381118282101715620005d457620005d462000599565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a62000599565b604052919050565b80516001600160a01b03811681146200064a57600080fd5b919050565b80516001600160401b03811681146200064a57600080fd5b805180151581146200064a57600080fd5b6000808284036080808212156200068e57600080fd5b6060808312156200069e57600080fd5b620006a8620005af565b9250620006b58662000632565b83526020620006c68188016200064f565b818501526040620006da6040890162000632565b604086015260608801519496506001600160401b0380861115620006fd57600080fd5b858901955089601f8701126200071257600080fd5b85518181111562000727576200072762000599565b62000737848260051b01620005ff565b818152848101925060079190911b87018401908b8211156200075857600080fd5b968401965b81881015620007d15786888d031215620007775760008081fd5b62000781620005da565b6200078c896200064f565b81526200079b868a0162000667565b86820152620007ac858a0162000632565b85820152620007bd878a0162000632565b81880152835296860196918401916200075d565b80985050505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b6000606082840312156200080c57600080fd5b62000816620005af565b620008218362000667565b815262000831602084016200064f565b6020820152620008446040840162000632565b60408201529392505050565b60805160a05160c05160e051615560620008d0600039600081816101d4015281816117aa01526124e90152600081816101a4015281816117840152612f2f0152600081816101680152818161175601528181611aab01526127de015260008181610a5a01528181610aa601528181610eff0152610f4b01526155606000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806381ff7048116100b2578063afcb95d711610081578063e9d68a8e11610066578063e9d68a8e14610491578063f2fde38b14610583578063f52121a51461059657600080fd5b8063afcb95d71461045e578063b1dc65a41461047e57600080fd5b806381ff7048146103cc57806385572ffb146103fc5780638b3643341461040a5780638da5cb5b1461043657600080fd5b80635e36480c116101095780637437ff9f116100ee5780637437ff9f146102cd57806379ba5097146103b15780637f63b711146103b957600080fd5b80635e36480c14610298578063666cab8d146102b857600080fd5b806306285c691461013b578063181f5a77146102275780631ef3817414610270578063542625af14610285575b600080fd5b610211604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161021e9190613a7e565b60405180910390f35b6102636040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b60405161021e9190613b31565b61028361027e366004613e0f565b6105a9565b005b6102836102933660046143d5565b610a57565b6102ab6102a6366004614500565b610c7f565b60405161021e91906145a3565b6102c0610d13565b60405161021e9190614603565b6103a46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260075463ffffffff808216835264010000000080830473ffffffffffffffffffffffffffffffffffffffff90811660208601527801000000000000000000000000000000000000000000000000840461ffff16958501959095527a0100000000000000000000000000000000000000000000000000009092048116606084015260085490811660808401520490911660a082015290565b60405161021e9190614616565b610283610d82565b6102836103c7366004614685565b610e7f565b6004546002546040805163ffffffff8085168252640100000000909404909316602084015282015260600161021e565b610283610136366004614769565b61041d6104183660046147a4565b610e93565b60405167ffffffffffffffff909116815260200161021e565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161021e565b60408051600181526000602082018190529181019190915260600161021e565b61028361048c366004614817565b610ea9565b61053361049f3660046148fc565b6040805160808101825260008082526020820181905291810182905260608101919091525067ffffffffffffffff166000908152600960209081526040918290208251608081018452815460ff81161515825273ffffffffffffffffffffffffffffffffffffffff610100909104811693820193909352600182015490921692820192909252600290910154606082015290565b6040805182511515815260208084015173ffffffffffffffffffffffffffffffffffffffff908116918301919091528383015116918101919091526060918201519181019190915260800161021e565b610283610591366004614919565b61113a565b6102836105a4366004614936565b61114b565b84518460ff16601f82111561061f576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f6f206d616e79207472616e736d697474657273000000000000000000000060448201526064015b60405180910390fd5b80600003610689576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610616565b610691611542565b61069a856115c5565b60065460005b8181101561071e5760056000600683815481106106bf576106bf61499a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016106a0565b50875160005b818110156109145760008a82815181106107405761074061499a565b602002602001015190506000600281111561075d5761075d614539565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561079c5761079c614539565b14610803576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610616565b73ffffffffffffffffffffffffffffffffffffffff8116610850576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561090057610900614539565b021790555090505050806001019050610724565b5088516109289060069060208c01906139e8565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908b1617179055600480546109ae9146913091906000906109809063ffffffff166149f8565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168d8d8d8d8d8d611809565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168e8e8e8e8e8e604051610a4299989796959493929190614a1b565b60405180910390a15050505050505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610ae2576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff46166024820152604401610616565b815181518114610b1e576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610c6f576000848281518110610b3d57610b3d61499a565b60200260200101519050600081602001515190506000858481518110610b6557610b6561499a565b6020026020010151905080518214610ba9576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610c60576000828281518110610bc857610bc861499a565b6020026020010151905080600014158015610c03575084602001518281518110610bf457610bf461499a565b60200260200101516080015181105b15610c575784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810183905260448101829052606401610616565b50600101610bac565b50505050806001019050610b21565b50610c7a83836118b4565b505050565b6000610c8d60016004614ab1565b6002610c9a608085614af3565b67ffffffffffffffff16610cae9190614b1a565b67ffffffffffffffff85166000908152600b6020526040812090610cd3608087614b31565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c166003811115610d0a57610d0a614539565b90505b92915050565b60606006805480602002602001604051908101604052809291908181526020018280548015610d7857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d4d575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610616565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e87611542565b610e9081611964565b50565b600080610ea08484611e15565b50949350505050565b610eb38787611f45565b600254883590808214610efc576040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610616565b467f000000000000000000000000000000000000000000000000000000000000000014610f7d576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610616565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526005602090815260408083208151808301909252805460ff8082168452929391929184019161010090910416600281111561100557611005614539565b600281111561101657611016614539565b905250905060028160200151600281111561103357611033614539565b14801561107a57506006816000015160ff16815481106110555761105561499a565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6110b0576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006110be856020614b1a565b6110c9886020614b1a565b6110d58b610144614b58565b6110df9190614b58565b6110e99190614b58565b905036811461112d576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610616565b5050505050505050505050565b611142611542565b610e9081611f8c565b333014611184576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201909252816111c1565b604080518082019091526000808252602082015281526020019060019003908161119a5790505b50610140840151519091501561127a576101408301516040805160608101909152602085015173ffffffffffffffffffffffffffffffffffffffff16608082015261127791908060a08101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252875167ffffffffffffffff1660208301528781015173ffffffffffffffffffffffffffffffffffffffff1691015261016086015185612081565b90505b6101208301515115801561129057506080830151155b806112b45750604083015173ffffffffffffffffffffffffffffffffffffffff163b155b80611301575060408301516112ff9073ffffffffffffffffffffffffffffffffffffffff167f85572ffb000000000000000000000000000000000000000000000000000000006123e3565b155b1561130b57505050565b600061131784836123ff565b600854909150640100000000900473ffffffffffffffffffffffffffffffffffffffff168015611426576040517fa219f6e500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063a219f6e590611393908590600401614c2c565b600060405180830381600087803b1580156113ad57600080fd5b505af19250505080156113be575060015b611426573d8080156113ec576040519150601f19603f3d011682016040523d82523d6000602084013e6113f1565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b600754608086015160408088015190517f3cf97983000000000000000000000000000000000000000000000000000000008152600093849364010000000090910473ffffffffffffffffffffffffffffffffffffffff1692633cf979839261149692899261138892600401614c3f565b6000604051808303816000875af11580156114b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114fb9190810190614ccd565b50915091508161153957806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610616565b565b6000818060200190518101906115db9190614d3b565b602081015190915073ffffffffffffffffffffffffffffffffffffffff1661162f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516007805460208085015160408087015160608089015163ffffffff9081167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff61ffff909416780100000000000000000000000000000000000000000000000002939093167fffff000000000000ffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff9687166401000000009081027fffffffffffffffff0000000000000000000000000000000000000000000000009a8b169c85169c909c179b909b1716179290921790965560808801516008805460a08b015186169099029890961691161795909517909255835192830184527f00000000000000000000000000000000000000000000000000000000000000008216835267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016908301527f0000000000000000000000000000000000000000000000000000000000000000168183015290517f1c86233479b9d798a31091d42b1a954067dcd6c898553d63bf993757d2a90aff916117fd918490614de7565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a60405160200161182d99989796959493929190614e9b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b81516000036118ee576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561195d576119558582815181106119235761192361499a565b60200260200101518461194f578583815181106119425761194261499a565b60200260200101516124af565b836124af565b600101611905565b5050505050565b60005b8151811015611e115760008282815181106119845761198461499a565b602002602001015190506000816000015190508067ffffffffffffffff166000036119e7576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b606082015173ffffffffffffffffffffffffffffffffffffffff16611a38576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600960205260409020600181015473ffffffffffffffffffffffffffffffffffffffff16611cb5576040517fe9d68a8e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9d68a8e90602401606060405180830381865afa158015611b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2b9190614f30565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16141580611b7d5750602081015167ffffffffffffffff1615155b15611bc0576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b611bef8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3612f29565b600283015560608401516001830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92831617905560408086015184547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010091909316029190911783555167ffffffffffffffff841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150611d4d565b6060830151600182015473ffffffffffffffffffffffffffffffffffffffff9081169116141580611d0a575060408301518154610100900473ffffffffffffffffffffffffffffffffffffffff908116911614155b15611d4d576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610616565b602083015181549015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617815560405167ffffffffffffffff8316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af079278490611dfb908490815460ff81161515825260081c73ffffffffffffffffffffffffffffffffffffffff90811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050611967565b5050565b67ffffffffffffffff8083166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091829116808203611f375767ffffffffffffffff8516600090815260096020526040902054610100900473ffffffffffffffffffffffffffffffffffffffff168015611f35576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015282169063856c824790602401602060405180830381865afa158015611f04573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f289190614f84565b6001935093505050611f3e565b505b9150600090505b9250929050565b6000611f5382840184614fa1565b60408051600080825260208201909252919250610c7a918391611f86565b6060815260200190600190039081611f715790505b506118b4565b3373ffffffffffffffffffffffffffffffffffffffff82160361200b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610616565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8360005b8551811015610ea05760008482815181106120a2576120a261499a565b60200260200101518060200190518101906120bd9190614fd6565b905060006120ce8260200151612fb9565b905061211073ffffffffffffffffffffffffffffffffffffffff82167faff2afbf000000000000000000000000000000000000000000000000000000006123e3565b61215e576040517fae9b4ce900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610616565b6000806122ab634059f55b60e01b6040518060e001604052808c6000015181526020018c6020015167ffffffffffffffff1681526020018c6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018d89815181106121c7576121c761499a565b602002602001015160200151815260200187600001518152602001876040015181526020018a89815181106121fe576121fe61499a565b6020026020010151815250604051602401612219919061508b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152600854859063ffffffff166113886084613014565b5091509150816122e957806040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b8051604014612333578051604080517f78ef802400000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604401610616565b6000808280602001905181019061234a9190615165565b915091506123578261313a565b8888815181106123695761236961499a565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808888815181106123ba576123ba61499a565b60200260200101516020018181525050505050505050806001019050612085565b949350505050565b60006123ee836131d1565b8015610d0a5750610d0a8383613235565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff1681526020018460200151604051602001612484919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b81516040517f58babe3300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906358babe3390602401602060405180830381865afa158015612545573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125699190615189565b156125ac576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b60208301515160008190036125ec576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836040015151811461262a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff82166000908152600960205260409020805460ff1661268a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b60008267ffffffffffffffff8111156126a5576126a5613b44565b6040519080825280602002602001820160405280156126ce578160200160208202803683370190505b50905060005b83811015612793576000876020015182815181106126f4576126f461499a565b6020026020010151905061270c818560020154613304565b83838151811061271e5761271e61499a565b6020026020010181815250508061018001518383815181106127425761274261499a565b60200260200101511461278a578061018001516040517f345039be00000000000000000000000000000000000000000000000000000000815260040161061691815260200190565b506001016126d4565b50606086015160808701516040517ffe41448f00000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263fe41448f92612815928a9288926004016151d7565b602060405180830381865afa158015612832573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612856919061521e565b90508060000361289e576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610616565b8551151560005b85811015612f1e576000896020015182815181106128c5576128c561499a565b6020026020010151905060006128df898360600151610c7f565b905060028160038111156128f5576128f5614539565b0361294b5760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612f16565b600081600381111561295f5761295f614539565b148061297c5750600381600381111561297a5761297a614539565b145b6129cc5760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b8315612a955760075460009063ffffffff166129e88742614ab1565b1190508080612a0857506003826003811115612a0657612a06614539565b145b612a4a576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b166004820152602401610616565b8a8481518110612a5c57612a5c61499a565b6020026020010151600014612a8f578a8481518110612a7d57612a7d61499a565b60200260200101518360800181815250505b50612afa565b6000816003811115612aa957612aa9614539565b14612afa5760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b600080612b0b8b8560200151611e15565b915091508015612c2b5760c084015167ffffffffffffffff16612b2f836001615237565b67ffffffffffffffff1614612bbf5760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60405180910390a150505050612f16565b67ffffffffffffffff8b81166000908152600a602090815260408083208883015173ffffffffffffffffffffffffffffffffffffffff168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169184169190911790555b6000836003811115612c3f57612c3f614539565b03612cdd5760c084015167ffffffffffffffff16612c5e836001615237565b67ffffffffffffffff1614612cdd5760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992612bae928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60008d604001518681518110612cf557612cf561499a565b60200260200101519050612d238561018001518d87606001518861014001515189610120015151865161348a565b612d338c866060015160016135e6565b600080612d4087846136c4565b91509150612d538e8860600151846135e6565b888015612d7157506003826003811115612d6f57612d6f614539565b145b15612db157866101800151816040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b6003826003811115612dc557612dc5614539565b14158015612de557506002826003811115612de257612de2614539565b14155b15612e26578d8760600151836040517f926c5a3e00000000000000000000000000000000000000000000000000000000815260040161061693929190615278565b6000866003811115612e3a57612e3a614539565b03612eb55767ffffffffffffffff808f166000908152600a602090815260408083208b83015173ffffffffffffffffffffffffffffffffffffffff168452909152812080549092169190612e8d8361529e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051612f069291906152bb565b60405180910390a4505050505050505b6001016128a5565b505050505050505050565b600081847f000000000000000000000000000000000000000000000000000000000000000085604051602001612f99949392919093845267ffffffffffffffff92831660208501529116604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b60008151602014612ff857816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106169190613b31565b610d0d8280602001905181019061300f919061521e565b61313a565b6000606060008361ffff1667ffffffffffffffff81111561303757613037613b44565b6040519080825280601f01601f191660200182016040528015613061576020820181803683370190505b509150863b613094577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a858110156130c7577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613100577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156131235750835b808352806000602085013e50955095509592505050565b600073ffffffffffffffffffffffffffffffffffffffff82118061315e5750600a82105b156131cd57604080516020810184905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261061691600401613b31565b5090565b60006131fd827f01ffc9a700000000000000000000000000000000000000000000000000000000613235565b8015610d0d575061322e827fffffffff00000000000000000000000000000000000000000000000000000000613235565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132ed575060208210155b80156132f95750600081115b979650505050505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016133a798979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016133e091906152db565b6040516020818303038152906040528051906020012087610160015160405160200161340c9190615366565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b6007547801000000000000000000000000000000000000000000000000900461ffff168311156134fa576040517fa1e5205a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b808314613547576040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b6007547a010000000000000000000000000000000000000000000000000000900463ffffffff168211156135de576007546040517f1fd8fd04000000000000000000000000000000000000000000000000000000008152600481018890527a01000000000000000000000000000000000000000000000000000090910463ffffffff16602482015260448101839052606401610616565b505050505050565b600060026135f5608085614af3565b67ffffffffffffffff166136099190614b1a565b67ffffffffffffffff85166000908152600b602052604081209192509081613632608087614b31565b67ffffffffffffffff16815260208101919091526040016000205490508161365c60016004614ab1565b901b19168183600381111561367357613673614539565b67ffffffffffffffff87166000908152600b602052604081209190921b929092179182916136a2608088614b31565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a5906137089087908790600401615379565b600060405180830381600087803b15801561372257600080fd5b505af1925050508015613733575060015b6139cd573d808015613761576040519150601f19603f3d011682016040523d82523d6000602084013e613766565b606091505b50600061377282615503565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216148061380557507fe1cd5509000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061385157507f8d666f60000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061389d57507f78ef8024000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b806138e957507f0c3b563c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061393557507fae9b4ce9000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061398157507f09c25325000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b156139925750600392509050611f3e565b856101800151826040517f2b11b8d900000000000000000000000000000000000000000000000000000000815260040161061692919061525f565b50506040805160208101909152600081526002909250929050565b828054828255906000526020600020908101928215613a62579160200282015b82811115613a6257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613a08565b506131cd9291505b808211156131cd5760008155600101613a6a565b60608101610d0d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b60005b83811015613ade578181015183820152602001613ac6565b50506000910152565b60008151808452613aff816020860160208601613ac3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d0a6020830184613ae7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405290565b6040516101a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b60405160a0810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516080810167ffffffffffffffff81118282101715613b9657613b96613b44565b6040516060810167ffffffffffffffff81118282101715613b9657613b96613b44565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c7057613c70613b44565b604052919050565b600067ffffffffffffffff821115613c9257613c92613b44565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114610e9057600080fd5b8035613cc981613c9c565b919050565b600082601f830112613cdf57600080fd5b81356020613cf4613cef83613c78565b613c29565b8083825260208201915060208460051b870101935086841115613d1657600080fd5b602086015b84811015613d3b578035613d2e81613c9c565b8352918301918301613d1b565b509695505050505050565b803560ff81168114613cc957600080fd5b600067ffffffffffffffff821115613d7157613d71613b44565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613dae57600080fd5b8135613dbc613cef82613d57565b818152846020838601011115613dd157600080fd5b816020850160208301376000918101602001919091529392505050565b67ffffffffffffffff81168114610e9057600080fd5b8035613cc981613dee565b60008060008060008060c08789031215613e2857600080fd5b863567ffffffffffffffff80821115613e4057600080fd5b613e4c8a838b01613cce565b97506020890135915080821115613e6257600080fd5b613e6e8a838b01613cce565b9650613e7c60408a01613d46565b95506060890135915080821115613e9257600080fd5b613e9e8a838b01613d9d565b9450613eac60808a01613e04565b935060a0890135915080821115613ec257600080fd5b50613ecf89828a01613d9d565b9150509295509295509295565b8015158114610e9057600080fd5b8035613cc981613edc565b600082601f830112613f0657600080fd5b81356020613f16613cef83613c78565b82815260069290921b84018101918181019086841115613f3557600080fd5b8286015b84811015613d3b5760408189031215613f525760008081fd5b613f5a613b73565b8135613f6581613c9c565b81528185013585820152835291830191604001613f39565b600082601f830112613f8e57600080fd5b81356020613f9e613cef83613c78565b82815260059290921b84018101918181019086841115613fbd57600080fd5b8286015b84811015613d3b57803567ffffffffffffffff811115613fe15760008081fd5b613fef8986838b0101613d9d565b845250918301918301613fc1565b60006101a0828403121561401057600080fd5b614018613b9c565b905061402382613e04565b815261403160208301613cbe565b602082015261404260408301613cbe565b604082015261405360608301613e04565b60608201526080820135608082015261406e60a08301613eea565b60a082015261407f60c08301613e04565b60c082015261409060e08301613cbe565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156140bd57600080fd5b6140c986838701613d9d565b838501526101409250828501359150808211156140e557600080fd5b6140f186838701613ef5565b8385015261016092508285013591508082111561410d57600080fd5b5061411a85828601613f7d565b82840152505061018080830135818301525092915050565b600082601f83011261414357600080fd5b81356020614153613cef83613c78565b82815260059290921b8401810191818101908684111561417257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156141965760008081fd5b6141a48986838b0101613ffd565b845250918301918301614176565b600082601f8301126141c357600080fd5b813560206141d3613cef83613c78565b82815260059290921b840181019181810190868411156141f257600080fd5b8286015b84811015613d3b57803567ffffffffffffffff8111156142165760008081fd5b6142248986838b0101613f7d565b8452509183019183016141f6565b600082601f83011261424357600080fd5b81356020614253613cef83613c78565b8083825260208201915060208460051b87010193508684111561427557600080fd5b602086015b84811015613d3b578035835291830191830161427a565b600082601f8301126142a257600080fd5b813560206142b2613cef83613c78565b82815260059290921b840181019181810190868411156142d157600080fd5b8286015b84811015613d3b57803567ffffffffffffffff808211156142f65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561432f5760008081fd5b614337613bc0565b614342888501613e04565b8152604080850135848111156143585760008081fd5b6143668e8b83890101614132565b8a840152506060808601358581111561437f5760008081fd5b61438d8f8c838a01016141b2565b83850152506080915081860135858111156143a85760008081fd5b6143b68f8c838a0101614232565b91840191909152509190930135908301525083529183019183016142d5565b60008060408084860312156143e957600080fd5b833567ffffffffffffffff8082111561440157600080fd5b61440d87838801614291565b945060209150818601358181111561442457600080fd5b8601601f8101881361443557600080fd5b8035614443613cef82613c78565b81815260059190911b8201840190848101908a83111561446257600080fd5b8584015b838110156144ee5780358681111561447e5760008081fd5b8501603f81018d136144905760008081fd5b878101356144a0613cef82613c78565b81815260059190911b82018a0190898101908f8311156144c05760008081fd5b928b01925b828410156144de5783358252928a0192908a01906144c5565b8652505050918601918601614466565b50809750505050505050509250929050565b6000806040838503121561451357600080fd5b823561451e81613dee565b9150602083013561452e81613dee565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6004811061459f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60208101610d0d8284614568565b60008151808452602080850194506020840160005b838110156145f857815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016145c6565b509495945050505050565b602081526000610d0a60208301846145b1565b60c08101610d0d828463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b6000602080838503121561469857600080fd5b823567ffffffffffffffff8111156146af57600080fd5b8301601f810185136146c057600080fd5b80356146ce613cef82613c78565b81815260079190911b820183019083810190878311156146ed57600080fd5b928401925b828410156132f9576080848903121561470b5760008081fd5b614713613be3565b843561471e81613dee565b81528486013561472d81613edc565b8187015260408581013561474081613c9c565b9082015260608581013561475381613c9c565b90820152825260809390930192908401906146f2565b60006020828403121561477b57600080fd5b813567ffffffffffffffff81111561479257600080fd5b820160a08185031215612fb257600080fd5b600080604083850312156147b757600080fd5b82356147c281613dee565b9150602083013561452e81613c9c565b60008083601f8401126147e457600080fd5b50813567ffffffffffffffff8111156147fc57600080fd5b6020830191508360208260051b8501011115611f3e57600080fd5b60008060008060008060008060e0898b03121561483357600080fd5b606089018a81111561484457600080fd5b8998503567ffffffffffffffff8082111561485e57600080fd5b818b0191508b601f83011261487257600080fd5b81358181111561488157600080fd5b8c602082850101111561489357600080fd5b6020830199508098505060808b01359150808211156148b157600080fd5b6148bd8c838d016147d2565b909750955060a08b01359150808211156148d657600080fd5b506148e38b828c016147d2565b999c989b50969995989497949560c00135949350505050565b60006020828403121561490e57600080fd5b8135612fb281613dee565b60006020828403121561492b57600080fd5b8135612fb281613c9c565b6000806040838503121561494957600080fd5b823567ffffffffffffffff8082111561496157600080fd5b61496d86838701613ffd565b9350602085013591508082111561498357600080fd5b5061499085828601613f7d565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103614a1157614a116149c9565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a4b8184018a6145b1565b90508281036080840152614a5f81896145b1565b905060ff871660a084015282810360c0840152614a7c8187613ae7565b905067ffffffffffffffff851660e0840152828103610100840152614aa18185613ae7565b9c9b505050505050505050505050565b81810381811115610d0d57610d0d6149c9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680614b0e57614b0e614ac4565b92169190910692915050565b8082028115828204841417610d0d57610d0d6149c9565b600067ffffffffffffffff80841680614b4c57614b4c614ac4565b92169190910492915050565b80820180821115610d0d57610d0d6149c9565b60008151808452602080850194506020840160005b838110156145f8578151805173ffffffffffffffffffffffffffffffffffffffff1688528301518388015260409096019590820190600101614b80565b8051825267ffffffffffffffff60208201511660208301526000604082015160a06040850152614bf060a0850182613ae7565b905060608301518482036060860152614c098282613ae7565b91505060808301518482036080860152614c238282614b6b565b95945050505050565b602081526000610d0a6020830184614bbd565b608081526000614c526080830187614bbd565b61ffff95909516602083015250604081019290925273ffffffffffffffffffffffffffffffffffffffff16606090910152919050565b600082601f830112614c9957600080fd5b8151614ca7613cef82613d57565b818152846020838601011115614cbc57600080fd5b6123db826020830160208701613ac3565b600080600060608486031215614ce257600080fd5b8351614ced81613edc565b602085015190935067ffffffffffffffff811115614d0a57600080fd5b614d1686828701614c88565b925050604084015190509250925092565b805163ffffffff81168114613cc957600080fd5b600060c08284031215614d4d57600080fd5b60405160c0810181811067ffffffffffffffff82111715614d7057614d70613b44565b604052614d7c83614d27565b81526020830151614d8c81613c9c565b6020820152604083015161ffff81168114614da657600080fd5b6040820152614db760608401614d27565b6060820152614dc860808401614d27565b608082015260a0830151614ddb81613c9c565b60a08201529392505050565b6101208101614e2d8285805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b612fb2606083018463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614ee28285018b6145b1565b91508382036080850152614ef6828a6145b1565b915060ff881660a085015283820360c0850152614f138288613ae7565b90861660e08501528381036101008501529050614aa18185613ae7565b600060608284031215614f4257600080fd5b614f4a613c06565b8251614f5581613edc565b81526020830151614f6581613dee565b60208201526040830151614f7881613c9c565b60408201529392505050565b600060208284031215614f9657600080fd5b8151612fb281613dee565b600060208284031215614fb357600080fd5b813567ffffffffffffffff811115614fca57600080fd5b6123db84828501614291565b600060208284031215614fe857600080fd5b815167ffffffffffffffff8082111561500057600080fd5b908301906060828603121561501457600080fd5b61501c613c06565b82518281111561502b57600080fd5b61503787828601614c88565b82525060208301518281111561504c57600080fd5b61505887828601614c88565b60208301525060408301518281111561507057600080fd5b61507c87828601614c88565b60408301525095945050505050565b602081526000825160e060208401526150a8610100840182613ae7565b905067ffffffffffffffff602085015116604084015260408401516150e5606085018273ffffffffffffffffffffffffffffffffffffffff169052565b506060840151608084015260808401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160a086015261512a8383613ae7565b925060a08601519150808584030160c08601526151478383613ae7565b925060c08601519150808584030160e086015250614c238282613ae7565b6000806040838503121561517857600080fd5b505080516020909101519092909150565b60006020828403121561519b57600080fd5b8151612fb281613edc565b60008151808452602080850194506020840160005b838110156145f8578151875295820195908201906001016151bb565b67ffffffffffffffff851681526080602082015260006151fa60808301866151a6565b828103604084015261520c81866151a6565b91505082606083015295945050505050565b60006020828403121561523057600080fd5b5051919050565b67ffffffffffffffff818116838216019080821115615258576152586149c9565b5092915050565b8281526040602082015260006123db6040830184613ae7565b67ffffffffffffffff848116825283166020820152606081016123db6040830184614568565b600067ffffffffffffffff808316818103614a1157614a116149c9565b6152c58184614568565b6040602082015260006123db6040830184613ae7565b602081526000610d0a6020830184614b6b565b60008282518085526020808601955060208260051b8401016020860160005b84811015615359577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952615347838351613ae7565b9884019892509083019060010161530d565b5090979650505050505050565b602081526000610d0a60208301846152ee565b6040815261539460408201845167ffffffffffffffff169052565b600060208401516153bd606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604084015173ffffffffffffffffffffffffffffffffffffffff8116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c084015161010061542b8185018367ffffffffffffffff169052565b60e086015191506101206154568186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061014091508282860152808701519250506101a061016081818701526154866101e0870185613ae7565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06101808188870301818901526154c58686614b6b565b9550828a015194508188870301848901526154e086866152ee565b9550808a01516101c089015250505050508281036020840152614c2381856152ee565b6000815160208301517fffffffff000000000000000000000000000000000000000000000000000000008082169350600483101561554b5780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", + Bin: "0x6101006040523480156200001257600080fd5b5060405162005e3238038062005e32833981016040819052620000359162000678565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf816200012c565b5050466080525081516001600160a01b0316620000ef576040516342bcdf7f60e11b815260040160405180910390fd5b81516001600160a01b0390811660a05260208301516001600160401b031660c05260408301511660e0526200012481620001d7565b505062000850565b336001600160a01b03821603620001865760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b81518110156200053a576000828281518110620001fb57620001fb620007e3565b60200260200101519050600081600001519050806001600160401b0316600003620002455760405163c39a620560e01b81526001600160401b038216600482015260240162000083565b60608201516001600160a01b031662000271576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260096020526040902060018101546001600160a01b0316620004395760a0516040516374eb454760e11b81526001600160401b03841660048201526000916001600160a01b03169063e9d68a8e90602401606060405180830381865afa158015620002ef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003159190620007f9565b905083606001516001600160a01b031681604001516001600160a01b03161415806200034d575060208101516001600160401b031615155b15620003785760405163c39a620560e01b81526001600160401b038416600482015260240162000083565b620003af8385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b36200053e60201b60201c565b600283015560608401516001830180546001600160a01b0319166001600160a01b039283161790556040808601518454610100600160a81b0319166101009190931602919091178355516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150620004a0565b606083015160018201546001600160a01b0390811691161415806200047557506040830151815461010090046001600160a01b03908116911614155b15620004a05760405163c39a620560e01b81526001600160401b038316600482015260240162000083565b6020830151815490151560ff199091161781556040516001600160401b038316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af07927849062000523908490815460ff81161515825260081c6001600160a01b0390811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050620001da565b5050565b60c05160408051602081018490526001600160401b0380871692820192909252911660608201526001600160a01b038316608082015260009060a0016040516020818303038152906040528051906020012090509392505050565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b0381118282101715620005d457620005d462000599565b60405290565b604051608081016001600160401b0381118282101715620005d457620005d462000599565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a62000599565b604052919050565b80516001600160a01b03811681146200064a57600080fd5b919050565b80516001600160401b03811681146200064a57600080fd5b805180151581146200064a57600080fd5b6000808284036080808212156200068e57600080fd5b6060808312156200069e57600080fd5b620006a8620005af565b9250620006b58662000632565b83526020620006c68188016200064f565b818501526040620006da6040890162000632565b604086015260608801519496506001600160401b0380861115620006fd57600080fd5b858901955089601f8701126200071257600080fd5b85518181111562000727576200072762000599565b62000737848260051b01620005ff565b818152848101925060079190911b87018401908b8211156200075857600080fd5b968401965b81881015620007d15786888d031215620007775760008081fd5b62000781620005da565b6200078c896200064f565b81526200079b868a0162000667565b86820152620007ac858a0162000632565b85820152620007bd878a0162000632565b81880152835296860196918401916200075d565b80985050505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b6000606082840312156200080c57600080fd5b62000816620005af565b620008218362000667565b815262000831602084016200064f565b6020820152620008446040840162000632565b60408201529392505050565b60805160a05160c05160e051615562620008d0600039600081816101d4015281816117ac01526124eb0152600081816101a4015281816117860152612f310152600081816101680152818161175801528181611aad01526127e0015260008181610a5a01528181610aa601528181610eff0152610f4b01526155626000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806381ff7048116100b2578063afcb95d711610081578063e9d68a8e11610066578063e9d68a8e14610491578063f2fde38b14610583578063f52121a51461059657600080fd5b8063afcb95d71461045e578063b1dc65a41461047e57600080fd5b806381ff7048146103cc57806385572ffb146103fc5780638b3643341461040a5780638da5cb5b1461043657600080fd5b80635e36480c116101095780637437ff9f116100ee5780637437ff9f146102cd57806379ba5097146103b15780637f63b711146103b957600080fd5b80635e36480c14610298578063666cab8d146102b857600080fd5b806306285c691461013b578063181f5a77146102275780631ef3817414610270578063542625af14610285575b600080fd5b610211604080516060810182526000808252602082018190529181019190915260405180606001604052807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161021e9190613a80565b60405180910390f35b6102636040518060400160405280601d81526020017f45564d3245564d4d756c74694f666652616d7020312e362e302d64657600000081525081565b60405161021e9190613b33565b61028361027e366004613e11565b6105a9565b005b6102836102933660046143d7565b610a57565b6102ab6102a6366004614502565b610c7f565b60405161021e91906145a5565b6102c0610d13565b60405161021e9190614605565b6103a46040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260075463ffffffff808216835264010000000080830473ffffffffffffffffffffffffffffffffffffffff90811660208601527801000000000000000000000000000000000000000000000000840461ffff16958501959095527a0100000000000000000000000000000000000000000000000000009092048116606084015260085490811660808401520490911660a082015290565b60405161021e9190614618565b610283610d82565b6102836103c7366004614687565b610e7f565b6004546002546040805163ffffffff8085168252640100000000909404909316602084015282015260600161021e565b61028361013636600461476b565b61041d6104183660046147a6565b610e93565b60405167ffffffffffffffff909116815260200161021e565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161021e565b60408051600181526000602082018190529181019190915260600161021e565b61028361048c366004614819565b610ea9565b61053361049f3660046148fe565b6040805160808101825260008082526020820181905291810182905260608101919091525067ffffffffffffffff166000908152600960209081526040918290208251608081018452815460ff81161515825273ffffffffffffffffffffffffffffffffffffffff610100909104811693820193909352600182015490921692820192909252600290910154606082015290565b6040805182511515815260208084015173ffffffffffffffffffffffffffffffffffffffff908116918301919091528383015116918101919091526060918201519181019190915260800161021e565b61028361059136600461491b565b61113a565b6102836105a4366004614938565b61114b565b84518460ff16601f82111561061f576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f6f206d616e79207472616e736d697474657273000000000000000000000060448201526064015b60405180910390fd5b80600003610689576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610616565b610691611544565b61069a856115c7565b60065460005b8181101561071e5760056000600683815481106106bf576106bf61499c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016106a0565b50875160005b818110156109145760008a82815181106107405761074061499c565b602002602001015190506000600281111561075d5761075d61453b565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260056020526040902054610100900460ff16600281111561079c5761079c61453b565b14610803576040517f89a6198900000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610616565b73ffffffffffffffffffffffffffffffffffffffff8116610850576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805180820190915260ff83168152602081016002905273ffffffffffffffffffffffffffffffffffffffff821660009081526005602090815260409091208251815460ff9091167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082168117835592840151919283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156109005761090061453b565b021790555090505050806001019050610724565b5088516109289060069060208c01906139ea565b506003805460ff838116610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909216908b1617179055600480546109ae9146913091906000906109809063ffffffff166149fa565b91906101000a81548163ffffffff021916908363ffffffff160217905563ffffffff168d8d8d8d8d8d61180b565b600260000181905550600060048054906101000a900463ffffffff169050436004806101000a81548163ffffffff021916908363ffffffff1602179055507f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0581600260000154600460009054906101000a900463ffffffff168e8e8e8e8e8e604051610a4299989796959493929190614a1d565b60405180910390a15050505050505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610ae2576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff46166024820152604401610616565b815181518114610b1e576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610c6f576000848281518110610b3d57610b3d61499c565b60200260200101519050600081602001515190506000858481518110610b6557610b6561499c565b6020026020010151905080518214610ba9576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610c60576000828281518110610bc857610bc861499c565b6020026020010151905080600014158015610c03575084602001518281518110610bf457610bf461499c565b60200260200101516080015181105b15610c575784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024810183905260448101829052606401610616565b50600101610bac565b50505050806001019050610b21565b50610c7a83836118b6565b505050565b6000610c8d60016004614ab3565b6002610c9a608085614af5565b67ffffffffffffffff16610cae9190614b1c565b67ffffffffffffffff85166000908152600b6020526040812090610cd3608087614b33565b67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002054901c166003811115610d0a57610d0a61453b565b90505b92915050565b60606006805480602002602001604051908101604052809291908181526020018280548015610d7857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610d4d575b5050505050905090565b60015473ffffffffffffffffffffffffffffffffffffffff163314610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610616565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e87611544565b610e9081611966565b50565b600080610ea08484611e17565b50949350505050565b610eb38787611f47565b600254883590808214610efc576040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610616565b467f000000000000000000000000000000000000000000000000000000000000000014610f7d576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610616565b6040805183815260208c81013560081c63ffffffff16908201527fb04e63db38c49950639fa09d29872f21f5d49d614f3a969d8adf3d4b52e41a62910160405180910390a13360009081526005602090815260408083208151808301909252805460ff808216845292939192918401916101009091041660028111156110055761100561453b565b60028111156110165761101661453b565b90525090506002816020015160028111156110335761103361453b565b14801561107a57506006816000015160ff16815481106110555761105561499c565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b6110b0576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060006110be856020614b1c565b6110c9886020614b1c565b6110d58b610144614b5a565b6110df9190614b5a565b6110e99190614b5a565b905036811461112d576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610616565b5050505050505050505050565b611142611544565b610e9081611f8e565b333014611184576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201909252816111c1565b604080518082019091526000808252602082015281526020019060019003908161119a5790505b50610140840151519091501561127a576101408301516040805160608101909152602085015173ffffffffffffffffffffffffffffffffffffffff16608082015261127791908060a08101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152908252875167ffffffffffffffff1660208301528781015173ffffffffffffffffffffffffffffffffffffffff1691015261016086015185612083565b90505b600061128684836123e5565b600854909150640100000000900473ffffffffffffffffffffffffffffffffffffffff168015611395576040517fa219f6e500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063a219f6e590611302908590600401614c2e565b600060405180830381600087803b15801561131c57600080fd5b505af192505050801561132d575060015b611395573d80801561135b576040519150601f19603f3d011682016040523d82523d6000602084013e611360565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106169190613b33565b610120850151511580156113ab57506080850151155b806113cf5750604085015173ffffffffffffffffffffffffffffffffffffffff163b155b8061141c5750604085015161141a9073ffffffffffffffffffffffffffffffffffffffff167f85572ffb00000000000000000000000000000000000000000000000000000000612495565b155b15611428575050505050565b600754608086015160408088015190517f3cf97983000000000000000000000000000000000000000000000000000000008152600093849364010000000090910473ffffffffffffffffffffffffffffffffffffffff1692633cf979839261149892899261138892600401614c41565b6000604051808303816000875af11580156114b7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526114fd9190810190614ccf565b50915091508161153b57806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106169190613b33565b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610616565b565b6000818060200190518101906115dd9190614d3d565b602081015190915073ffffffffffffffffffffffffffffffffffffffff16611631576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516007805460208085015160408087015160608089015163ffffffff9081167a010000000000000000000000000000000000000000000000000000027fffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffff61ffff909416780100000000000000000000000000000000000000000000000002939093167fffff000000000000ffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff9687166401000000009081027fffffffffffffffff0000000000000000000000000000000000000000000000009a8b169c85169c909c179b909b1716179290921790965560808801516008805460a08b015186169099029890961691161795909517909255835192830184527f00000000000000000000000000000000000000000000000000000000000000008216835267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016908301527f0000000000000000000000000000000000000000000000000000000000000000168183015290517f1c86233479b9d798a31091d42b1a954067dcd6c898553d63bf993757d2a90aff916117ff918490614de9565b60405180910390a15050565b6000808a8a8a8a8a8a8a8a8a60405160200161182f99989796959493929190614e9d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150509998505050505050505050565b81516000036118f0576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561195f576119578582815181106119255761192561499c565b602002602001015184611951578583815181106119445761194461499c565b60200260200101516124b1565b836124b1565b600101611907565b5050505050565b60005b8151811015611e135760008282815181106119865761198661499c565b602002602001015190506000816000015190508067ffffffffffffffff166000036119e9576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b606082015173ffffffffffffffffffffffffffffffffffffffff16611a3a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600960205260409020600181015473ffffffffffffffffffffffffffffffffffffffff16611cb7576040517fe9d68a8e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063e9d68a8e90602401606060405180830381865afa158015611b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2d9190614f32565b9050836060015173ffffffffffffffffffffffffffffffffffffffff16816040015173ffffffffffffffffffffffffffffffffffffffff16141580611b7f5750602081015167ffffffffffffffff1615155b15611bc2576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b611bf18385606001517f8acd72527118c8324937b1a42e02cd246697c3b633f1742f3cae11de233722b3612f2b565b600283015560608401516001830180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92831617905560408086015184547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010091909316029190911783555167ffffffffffffffff841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a150611d4f565b6060830151600182015473ffffffffffffffffffffffffffffffffffffffff9081169116141580611d0c575060408301518154610100900473ffffffffffffffffffffffffffffffffffffffff908116911614155b15611d4f576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610616565b602083015181549015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911617815560405167ffffffffffffffff8316907fdba8597411dc0624375cfff476f6173674609571f4d98d294dd3a47af079278490611dfd908490815460ff81161515825260081c73ffffffffffffffffffffffffffffffffffffffff90811660208301526001830154166040820152600290910154606082015260800190565b60405180910390a2505050806001019050611969565b5050565b67ffffffffffffffff8083166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120549091829116808203611f395767ffffffffffffffff8516600090815260096020526040902054610100900473ffffffffffffffffffffffffffffffffffffffff168015611f37576040517f856c824700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015282169063856c824790602401602060405180830381865afa158015611f06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f2a9190614f86565b6001935093505050611f40565b505b9150600090505b9250929050565b6000611f5582840184614fa3565b60408051600080825260208201909252919250610c7a918391611f88565b6060815260200190600190039081611f735790505b506118b6565b3373ffffffffffffffffffffffffffffffffffffffff82160361200d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610616565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b8360005b8551811015610ea05760008482815181106120a4576120a461499c565b60200260200101518060200190518101906120bf9190614fd8565b905060006120d08260200151612fbb565b905061211273ffffffffffffffffffffffffffffffffffffffff82167faff2afbf00000000000000000000000000000000000000000000000000000000612495565b612160576040517fae9b4ce900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610616565b6000806122ad634059f55b60e01b6040518060e001604052808c6000015181526020018c6020015167ffffffffffffffff1681526020018c6040015173ffffffffffffffffffffffffffffffffffffffff1681526020018d89815181106121c9576121c961499c565b602002602001015160200151815260200187600001518152602001876040015181526020018a89815181106122005761220061499c565b602002602001015181525060405160240161221b919061508d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152600854859063ffffffff166113886084613016565b5091509150816122eb57806040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106169190613b33565b8051604014612335578051604080517f78ef802400000000000000000000000000000000000000000000000000000000815260048101919091526024810191909152604401610616565b6000808280602001905181019061234c9190615167565b915091506123598261313c565b88888151811061236b5761236b61499c565b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050808888815181106123bc576123bc61499c565b60200260200101516020018181525050505050505050806001019050612087565b949350505050565b6040805160a08101825260008082526020820152606091810182905281810182905260808101919091526040518060a001604052808461018001518152602001846000015167ffffffffffffffff168152602001846020015160405160200161246a919073ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6040516020818303038152906040528152602001846101200151815260200183815250905092915050565b60006124a0836131d3565b8015610d0a5750610d0a8383613237565b81516040517f58babe3300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906358babe3390602401602060405180830381865afa158015612547573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061256b919061518b565b156125ae576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610616565b60208301515160008190036125ee576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836040015151811461262c576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff82166000908152600960205260409020805460ff1661268c576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610616565b60008267ffffffffffffffff8111156126a7576126a7613b46565b6040519080825280602002602001820160405280156126d0578160200160208202803683370190505b50905060005b83811015612795576000876020015182815181106126f6576126f661499c565b6020026020010151905061270e818560020154613306565b8383815181106127205761272061499c565b6020026020010181815250508061018001518383815181106127445761274461499c565b60200260200101511461278c578061018001516040517f345039be00000000000000000000000000000000000000000000000000000000815260040161061691815260200190565b506001016126d6565b50606086015160808701516040517ffe41448f00000000000000000000000000000000000000000000000000000000815260009273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263fe41448f92612817928a9288926004016151d9565b602060405180830381865afa158015612834573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128589190615220565b9050806000036128a0576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610616565b8551151560005b85811015612f20576000896020015182815181106128c7576128c761499c565b6020026020010151905060006128e1898360600151610c7f565b905060028160038111156128f7576128f761453b565b0361294d5760608201516040805167ffffffffffffffff808d16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a15050612f18565b60008160038111156129615761296161453b565b148061297e5750600381600381111561297c5761297c61453b565b145b6129ce5760608201516040517f25507e7f00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b8315612a975760075460009063ffffffff166129ea8742614ab3565b1190508080612a0a57506003826003811115612a0857612a0861453b565b145b612a4c576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8b166004820152602401610616565b8a8481518110612a5e57612a5e61499c565b6020026020010151600014612a91578a8481518110612a7f57612a7f61499c565b60200260200101518360800181815250505b50612afc565b6000816003811115612aab57612aab61453b565b14612afc5760608201516040517f3ef2a99c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808c1660048301529091166024820152604401610616565b600080612b0d8b8560200151611e17565b915091508015612c2d5760c084015167ffffffffffffffff16612b31836001615239565b67ffffffffffffffff1614612bc15760c084015160208501516040517f5444a3301c7c42dd164cbf6ba4b72bf02504f86c049b06a27fc2b662e334bdbd92612bb0928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60405180910390a150505050612f18565b67ffffffffffffffff8b81166000908152600a602090815260408083208883015173ffffffffffffffffffffffffffffffffffffffff168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000169184169190911790555b6000836003811115612c4157612c4161453b565b03612cdf5760c084015167ffffffffffffffff16612c60836001615239565b67ffffffffffffffff1614612cdf5760c084015160208501516040517f852dc8e405695593e311bd83991cf39b14a328f304935eac6d3d55617f911d8992612bb0928f9267ffffffffffffffff938416815291909216602082015273ffffffffffffffffffffffffffffffffffffffff91909116604082015260600190565b60008d604001518681518110612cf757612cf761499c565b60200260200101519050612d258561018001518d87606001518861014001515189610120015151865161348c565b612d358c866060015160016135e8565b600080612d4287846136c6565b91509150612d558e8860600151846135e8565b888015612d7357506003826003811115612d7157612d7161453b565b145b15612db357866101800151816040517f2b11b8d9000000000000000000000000000000000000000000000000000000008152600401610616929190615261565b6003826003811115612dc757612dc761453b565b14158015612de757506002826003811115612de457612de461453b565b14155b15612e28578d8760600151836040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526004016106169392919061527a565b6000866003811115612e3c57612e3c61453b565b03612eb75767ffffffffffffffff808f166000908152600a602090815260408083208b83015173ffffffffffffffffffffffffffffffffffffffff168452909152812080549092169190612e8f836152a0565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550505b866101800151876060015167ffffffffffffffff168f67ffffffffffffffff167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051612f089291906152bd565b60405180910390a4505050505050505b6001016128a7565b505050505050505050565b600081847f000000000000000000000000000000000000000000000000000000000000000085604051602001612f9b949392919093845267ffffffffffffffff92831660208501529116604083015273ffffffffffffffffffffffffffffffffffffffff16606082015260800190565b6040516020818303038152906040528051906020012090505b9392505050565b60008151602014612ffa57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106169190613b33565b610d0d828060200190518101906130119190615220565b61313c565b6000606060008361ffff1667ffffffffffffffff81111561303957613039613b46565b6040519080825280601f01601f191660200182016040528015613063576020820181803683370190505b509150863b613096577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a858110156130c9577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613102577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156131255750835b808352806000602085013e50955095509592505050565b600073ffffffffffffffffffffffffffffffffffffffff8211806131605750600a82105b156131cf57604080516020810184905201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f8d666f6000000000000000000000000000000000000000000000000000000000825261061691600401613b33565b5090565b60006131ff827f01ffc9a700000000000000000000000000000000000000000000000000000000613237565b8015610d0d5750613230827fffffffff00000000000000000000000000000000000000000000000000000000613237565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156132ef575060208210155b80156132fb5750600081115b979650505050505050565b60008060001b8284602001518560400151866060015187608001518860a001518960c001518a60e001518b61010001516040516020016133a998979695949392919073ffffffffffffffffffffffffffffffffffffffff9889168152968816602088015267ffffffffffffffff95861660408801526060870194909452911515608086015290921660a0840152921660c082015260e08101919091526101000190565b60405160208183030381529060405280519060200120856101200151805190602001208661014001516040516020016133e291906152dd565b6040516020818303038152906040528051906020012087610160015160405160200161340e9190615368565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b6007547801000000000000000000000000000000000000000000000000900461ffff168311156134fc576040517fa1e5205a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b808314613549576040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808716600483015285166024820152604401610616565b6007547a010000000000000000000000000000000000000000000000000000900463ffffffff168211156135e0576007546040517f1fd8fd04000000000000000000000000000000000000000000000000000000008152600481018890527a01000000000000000000000000000000000000000000000000000090910463ffffffff16602482015260448101839052606401610616565b505050505050565b600060026135f7608085614af5565b67ffffffffffffffff1661360b9190614b1c565b67ffffffffffffffff85166000908152600b602052604081209192509081613634608087614b33565b67ffffffffffffffff16815260208101919091526040016000205490508161365e60016004614ab3565b901b1916818360038111156136755761367561453b565b67ffffffffffffffff87166000908152600b602052604081209190921b929092179182916136a4608088614b33565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517ff52121a5000000000000000000000000000000000000000000000000000000008152600090606090309063f52121a59061370a908790879060040161537b565b600060405180830381600087803b15801561372457600080fd5b505af1925050508015613735575060015b6139cf573d808015613763576040519150601f19603f3d011682016040523d82523d6000602084013e613768565b606091505b50600061377482615505565b90507f0a8d6e8c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216148061380757507fe1cd5509000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061385357507f8d666f60000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061389f57507f78ef8024000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b806138eb57507f0c3b563c000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061393757507fae9b4ce9000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b8061398357507f09c25325000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008216145b156139945750600392509050611f40565b856101800151826040517f2b11b8d9000000000000000000000000000000000000000000000000000000008152600401610616929190615261565b50506040805160208101909152600081526002909250929050565b828054828255906000526020600020908101928215613a64579160200282015b82811115613a6457825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190613a0a565b506131cf9291505b808211156131cf5760008155600101613a6c565b60608101610d0d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b60005b83811015613ae0578181015183820152602001613ac8565b50506000910152565b60008151808452613b01816020860160208601613ac5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610d0a6020830184613ae9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715613b9857613b98613b46565b60405290565b6040516101a0810167ffffffffffffffff81118282101715613b9857613b98613b46565b60405160a0810167ffffffffffffffff81118282101715613b9857613b98613b46565b6040516080810167ffffffffffffffff81118282101715613b9857613b98613b46565b6040516060810167ffffffffffffffff81118282101715613b9857613b98613b46565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c7257613c72613b46565b604052919050565b600067ffffffffffffffff821115613c9457613c94613b46565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff81168114610e9057600080fd5b8035613ccb81613c9e565b919050565b600082601f830112613ce157600080fd5b81356020613cf6613cf183613c7a565b613c2b565b8083825260208201915060208460051b870101935086841115613d1857600080fd5b602086015b84811015613d3d578035613d3081613c9e565b8352918301918301613d1d565b509695505050505050565b803560ff81168114613ccb57600080fd5b600067ffffffffffffffff821115613d7357613d73613b46565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613db057600080fd5b8135613dbe613cf182613d59565b818152846020838601011115613dd357600080fd5b816020850160208301376000918101602001919091529392505050565b67ffffffffffffffff81168114610e9057600080fd5b8035613ccb81613df0565b60008060008060008060c08789031215613e2a57600080fd5b863567ffffffffffffffff80821115613e4257600080fd5b613e4e8a838b01613cd0565b97506020890135915080821115613e6457600080fd5b613e708a838b01613cd0565b9650613e7e60408a01613d48565b95506060890135915080821115613e9457600080fd5b613ea08a838b01613d9f565b9450613eae60808a01613e06565b935060a0890135915080821115613ec457600080fd5b50613ed189828a01613d9f565b9150509295509295509295565b8015158114610e9057600080fd5b8035613ccb81613ede565b600082601f830112613f0857600080fd5b81356020613f18613cf183613c7a565b82815260069290921b84018101918181019086841115613f3757600080fd5b8286015b84811015613d3d5760408189031215613f545760008081fd5b613f5c613b75565b8135613f6781613c9e565b81528185013585820152835291830191604001613f3b565b600082601f830112613f9057600080fd5b81356020613fa0613cf183613c7a565b82815260059290921b84018101918181019086841115613fbf57600080fd5b8286015b84811015613d3d57803567ffffffffffffffff811115613fe35760008081fd5b613ff18986838b0101613d9f565b845250918301918301613fc3565b60006101a0828403121561401257600080fd5b61401a613b9e565b905061402582613e06565b815261403360208301613cc0565b602082015261404460408301613cc0565b604082015261405560608301613e06565b60608201526080820135608082015261407060a08301613eec565b60a082015261408160c08301613e06565b60c082015261409260e08301613cc0565b60e082015261010082810135908201526101208083013567ffffffffffffffff808211156140bf57600080fd5b6140cb86838701613d9f565b838501526101409250828501359150808211156140e757600080fd5b6140f386838701613ef7565b8385015261016092508285013591508082111561410f57600080fd5b5061411c85828601613f7f565b82840152505061018080830135818301525092915050565b600082601f83011261414557600080fd5b81356020614155613cf183613c7a565b82815260059290921b8401810191818101908684111561417457600080fd5b8286015b84811015613d3d57803567ffffffffffffffff8111156141985760008081fd5b6141a68986838b0101613fff565b845250918301918301614178565b600082601f8301126141c557600080fd5b813560206141d5613cf183613c7a565b82815260059290921b840181019181810190868411156141f457600080fd5b8286015b84811015613d3d57803567ffffffffffffffff8111156142185760008081fd5b6142268986838b0101613f7f565b8452509183019183016141f8565b600082601f83011261424557600080fd5b81356020614255613cf183613c7a565b8083825260208201915060208460051b87010193508684111561427757600080fd5b602086015b84811015613d3d578035835291830191830161427c565b600082601f8301126142a457600080fd5b813560206142b4613cf183613c7a565b82815260059290921b840181019181810190868411156142d357600080fd5b8286015b84811015613d3d57803567ffffffffffffffff808211156142f85760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156143315760008081fd5b614339613bc2565b614344888501613e06565b81526040808501358481111561435a5760008081fd5b6143688e8b83890101614134565b8a84015250606080860135858111156143815760008081fd5b61438f8f8c838a01016141b4565b83850152506080915081860135858111156143aa5760008081fd5b6143b88f8c838a0101614234565b91840191909152509190930135908301525083529183019183016142d7565b60008060408084860312156143eb57600080fd5b833567ffffffffffffffff8082111561440357600080fd5b61440f87838801614293565b945060209150818601358181111561442657600080fd5b8601601f8101881361443757600080fd5b8035614445613cf182613c7a565b81815260059190911b8201840190848101908a83111561446457600080fd5b8584015b838110156144f0578035868111156144805760008081fd5b8501603f81018d136144925760008081fd5b878101356144a2613cf182613c7a565b81815260059190911b82018a0190898101908f8311156144c25760008081fd5b928b01925b828410156144e05783358252928a0192908a01906144c7565b8652505050918601918601614468565b50809750505050505050509250929050565b6000806040838503121561451557600080fd5b823561452081613df0565b9150602083013561453081613df0565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600481106145a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b60208101610d0d828461456a565b60008151808452602080850194506020840160005b838110156145fa57815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016145c8565b509495945050505050565b602081526000610d0a60208301846145b3565b60c08101610d0d828463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b6000602080838503121561469a57600080fd5b823567ffffffffffffffff8111156146b157600080fd5b8301601f810185136146c257600080fd5b80356146d0613cf182613c7a565b81815260079190911b820183019083810190878311156146ef57600080fd5b928401925b828410156132fb576080848903121561470d5760008081fd5b614715613be5565b843561472081613df0565b81528486013561472f81613ede565b8187015260408581013561474281613c9e565b9082015260608581013561475581613c9e565b90820152825260809390930192908401906146f4565b60006020828403121561477d57600080fd5b813567ffffffffffffffff81111561479457600080fd5b820160a08185031215612fb457600080fd5b600080604083850312156147b957600080fd5b82356147c481613df0565b9150602083013561453081613c9e565b60008083601f8401126147e657600080fd5b50813567ffffffffffffffff8111156147fe57600080fd5b6020830191508360208260051b8501011115611f4057600080fd5b60008060008060008060008060e0898b03121561483557600080fd5b606089018a81111561484657600080fd5b8998503567ffffffffffffffff8082111561486057600080fd5b818b0191508b601f83011261487457600080fd5b81358181111561488357600080fd5b8c602082850101111561489557600080fd5b6020830199508098505060808b01359150808211156148b357600080fd5b6148bf8c838d016147d4565b909750955060a08b01359150808211156148d857600080fd5b506148e58b828c016147d4565b999c989b50969995989497949560c00135949350505050565b60006020828403121561491057600080fd5b8135612fb481613df0565b60006020828403121561492d57600080fd5b8135612fb481613c9e565b6000806040838503121561494b57600080fd5b823567ffffffffffffffff8082111561496357600080fd5b61496f86838701613fff565b9350602085013591508082111561498557600080fd5b5061499285828601613f7f565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600063ffffffff808316818103614a1357614a136149cb565b6001019392505050565b600061012063ffffffff808d1684528b6020850152808b16604085015250806060840152614a4d8184018a6145b3565b90508281036080840152614a6181896145b3565b905060ff871660a084015282810360c0840152614a7e8187613ae9565b905067ffffffffffffffff851660e0840152828103610100840152614aa38185613ae9565b9c9b505050505050505050505050565b81810381811115610d0d57610d0d6149cb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600067ffffffffffffffff80841680614b1057614b10614ac6565b92169190910692915050565b8082028115828204841417610d0d57610d0d6149cb565b600067ffffffffffffffff80841680614b4e57614b4e614ac6565b92169190910492915050565b80820180821115610d0d57610d0d6149cb565b60008151808452602080850194506020840160005b838110156145fa578151805173ffffffffffffffffffffffffffffffffffffffff1688528301518388015260409096019590820190600101614b82565b8051825267ffffffffffffffff60208201511660208301526000604082015160a06040850152614bf260a0850182613ae9565b905060608301518482036060860152614c0b8282613ae9565b91505060808301518482036080860152614c258282614b6d565b95945050505050565b602081526000610d0a6020830184614bbf565b608081526000614c546080830187614bbf565b61ffff95909516602083015250604081019290925273ffffffffffffffffffffffffffffffffffffffff16606090910152919050565b600082601f830112614c9b57600080fd5b8151614ca9613cf182613d59565b818152846020838601011115614cbe57600080fd5b6123dd826020830160208701613ac5565b600080600060608486031215614ce457600080fd5b8351614cef81613ede565b602085015190935067ffffffffffffffff811115614d0c57600080fd5b614d1886828701614c8a565b925050604084015190509250925092565b805163ffffffff81168114613ccb57600080fd5b600060c08284031215614d4f57600080fd5b60405160c0810181811067ffffffffffffffff82111715614d7257614d72613b46565b604052614d7e83614d29565b81526020830151614d8e81613c9e565b6020820152604083015161ffff81168114614da857600080fd5b6040820152614db960608401614d29565b6060820152614dca60808401614d29565b608082015260a0830151614ddd81613c9e565b60a08201529392505050565b6101208101614e2f8285805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015167ffffffffffffffff169084015260409182015116910152565b612fb4606083018463ffffffff808251168352602082015173ffffffffffffffffffffffffffffffffffffffff808216602086015261ffff60408501511660408601528260608501511660608601528260808501511660808601528060a08501511660a08601525050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b166040850152816060850152614ee48285018b6145b3565b91508382036080850152614ef8828a6145b3565b915060ff881660a085015283820360c0850152614f158288613ae9565b90861660e08501528381036101008501529050614aa38185613ae9565b600060608284031215614f4457600080fd5b614f4c613c08565b8251614f5781613ede565b81526020830151614f6781613df0565b60208201526040830151614f7a81613c9e565b60408201529392505050565b600060208284031215614f9857600080fd5b8151612fb481613df0565b600060208284031215614fb557600080fd5b813567ffffffffffffffff811115614fcc57600080fd5b6123dd84828501614293565b600060208284031215614fea57600080fd5b815167ffffffffffffffff8082111561500257600080fd5b908301906060828603121561501657600080fd5b61501e613c08565b82518281111561502d57600080fd5b61503987828601614c8a565b82525060208301518281111561504e57600080fd5b61505a87828601614c8a565b60208301525060408301518281111561507257600080fd5b61507e87828601614c8a565b60408301525095945050505050565b602081526000825160e060208401526150aa610100840182613ae9565b905067ffffffffffffffff602085015116604084015260408401516150e7606085018273ffffffffffffffffffffffffffffffffffffffff169052565b506060840151608084015260808401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160a086015261512c8383613ae9565b925060a08601519150808584030160c08601526151498383613ae9565b925060c08601519150808584030160e086015250614c258282613ae9565b6000806040838503121561517a57600080fd5b505080516020909101519092909150565b60006020828403121561519d57600080fd5b8151612fb481613ede565b60008151808452602080850194506020840160005b838110156145fa578151875295820195908201906001016151bd565b67ffffffffffffffff851681526080602082015260006151fc60808301866151a8565b828103604084015261520e81866151a8565b91505082606083015295945050505050565b60006020828403121561523257600080fd5b5051919050565b67ffffffffffffffff81811683821601908082111561525a5761525a6149cb565b5092915050565b8281526040602082015260006123dd6040830184613ae9565b67ffffffffffffffff848116825283166020820152606081016123dd604083018461456a565b600067ffffffffffffffff808316818103614a1357614a136149cb565b6152c7818461456a565b6040602082015260006123dd6040830184613ae9565b602081526000610d0a6020830184614b6d565b60008282518085526020808601955060208260051b8401016020860160005b8481101561535b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952615349838351613ae9565b9884019892509083019060010161530f565b5090979650505050505050565b602081526000610d0a60208301846152f0565b6040815261539660408201845167ffffffffffffffff169052565b600060208401516153bf606084018273ffffffffffffffffffffffffffffffffffffffff169052565b50604084015173ffffffffffffffffffffffffffffffffffffffff8116608084015250606084015167ffffffffffffffff811660a084015250608084015160c083015260a084015180151560e08401525060c084015161010061542d8185018367ffffffffffffffff169052565b60e086015191506101206154588186018473ffffffffffffffffffffffffffffffffffffffff169052565b81870151925061014091508282860152808701519250506101a061016081818701526154886101e0870185613ae9565b93508288015192507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc06101808188870301818901526154c78686614b6d565b9550828a015194508188870301848901526154e286866152f0565b9550808a01516101c089015250505050508281036020840152614c2581856152f0565b6000815160208301517fffffffff000000000000000000000000000000000000000000000000000000008082169350600483101561554d5780818460040360031b1b83161693505b50505091905056fea164736f6c6343000818000a", } var EVM2EVMMultiOffRampABI = EVM2EVMMultiOffRampMetaData.ABI 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 ad76a6bd41..956b5fd28a 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 @@ -9,7 +9,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 bd56fec69d252bd9b87b5dd647e2eca937cf0b92674c824aa5f17427eba1c657 custom_token_pool: ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.abi ../../../contracts/solc/v0.8.24/CustomTokenPool/CustomTokenPool.bin 488bd34d63be7b731f4fbdf0cd353f7e4fbee990cfa4db26be91973297d3f803 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin f72f9f4562a6f788f9f59197f34bd603476fe8c2555c9eebba72e9d9b445cbcc -evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 20b1d8e51d01d512ecacca05eccdd0b8bd76a7cff132702a7f26d638fab53f0b +evm_2_evm_multi_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOffRamp/EVM2EVMMultiOffRamp.bin 342d0ac906ffc721f31b359bb6c3233c7260ef871b6ef6d0f1c3a0809318fd71 evm_2_evm_multi_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMMultiOnRamp/EVM2EVMMultiOnRamp.bin 86bb3fe6408b720e626affff65df424e587baae48396e3e0d3e3e3725343ab95 evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin 0daedb073a1b3563eb014f3363e0c796ade734ffbb217562f47101fdf0837c4a evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin d8a663d8071b93bf09367f406c532fa87f2a4b156e8db250f922ca979cb1fab9