Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
RMNRemote
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 80000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; import {IRMN} from "../interfaces/IRMN.sol"; import {IRMNRemote} from "../interfaces/IRMNRemote.sol"; import {ITypeAndVersion} from "@chainlink/shared/interfaces/ITypeAndVersion.sol"; import {Internal} from "../libraries/Internal.sol"; import {Ownable2StepMsgSender} from "@chainlink/shared/access/Ownable2StepMsgSender.sol"; import {EnumerableSet} from "@chainlink/shared/enumerable/EnumerableSetWithBytes16.sol"; /// @dev An active curse on this subject will cause isCursed() and isCursed(bytes16) to return true. Use this subject /// for issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of /// using the local chain selector as a subject. bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; /// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. /// @dev This contract implements both the new IRMNRemote interface and the legacy IRMN interface. This is to allow for /// a seamless migration from the legacy RMN contract to this one. The only function that has been dropped in the newer /// interface is `isBlessed`. For the `isBlessed` function, this contract relays the call to the legacy RMN contract. contract RMNRemote is Ownable2StepMsgSender, ITypeAndVersion, IRMNRemote, IRMN { using EnumerableSet for EnumerableSet.Bytes16Set; error AlreadyCursed(bytes16 subject); error ConfigNotSet(); error DuplicateOnchainPublicKey(); error InvalidSignature(); error InvalidSignerOrder(); error NotEnoughSigners(); error NotCursed(bytes16 subject); error OutOfOrderSignatures(); error ThresholdNotMet(); error UnexpectedSigner(); error ZeroValueNotAllowed(); error IsBlessedNotAvailable(); event ConfigSet(uint32 indexed version, Config config); event Cursed(bytes16[] subjects); event Uncursed(bytes16[] subjects); /// @dev the configuration of an RMN signer. struct Signer { address onchainPublicKey; // ─╮ For signing reports. uint64 nodeIndex; // ─────────╯ Maps to nodes in home chain config, should be strictly increasing. } /// @dev the contract config. struct Config { bytes32 rmnHomeContractConfigDigest; // Digest of the RMNHome contract config. Signer[] signers; // List of signers. uint64 fSign; // Max number of faulty RMN nodes; f+1 signers are required to verify a report, must configure 2f+1 signers in total. } /// @dev part of the payload that RMN nodes sign: keccak256(abi.encode(RMN_V1_6_ANY2EVM_REPORT, report)). /// @dev this struct is only ever abi-encoded and hashed; it is never stored. struct Report { uint256 destChainId; // To guard against chain selector misconfiguration. uint64 destChainSelector; // ────────╮ The chain selector of the destination chain. address rmnRemoteContractAddress; // ─╯ The address of this contract. address offrampAddress; // The address of the offramp on the same chain as this contract. bytes32 rmnHomeContractConfigDigest; // The digest of the RMNHome contract config. Internal.MerkleRoot[] merkleRoots; // The dest lane updates. } /// @dev this is included in the preimage of the digest that RMN nodes sign. bytes32 private constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); string public constant override typeAndVersion = "RMNRemote 1.6.0"; uint64 internal immutable i_localChainSelector; IRMN internal immutable i_legacyRMN; Config private s_config; uint32 private s_configCount; /// @dev RMN nodes only generate sigs with v=27; making this constant allows us to save gas by not transmitting v. /// @dev Any valid ECDSA sig (r, s, v) can be "flipped" into (r, s*, v*) without knowing the private key (where v=27 or 28 for secp256k1) /// https://github.com/kadenzipfel/smart-contract-vulnerabilities/blob/master/vulnerabilities/signature-malleability.md. uint8 private constant ECDSA_RECOVERY_V = 27; EnumerableSet.Bytes16Set private s_cursedSubjects; mapping(address signer => bool exists) private s_signers; // for more gas efficient verify. /// @param localChainSelector the chain selector of the chain this contract is deployed to. constructor(uint64 localChainSelector, IRMN legacyRMN) { if (localChainSelector == 0) revert ZeroValueNotAllowed(); i_localChainSelector = localChainSelector; i_legacyRMN = legacyRMN; } // ================================================================ // │ Verification │ // ================================================================ /// @inheritdoc IRMNRemote function verify( address offRampAddress, Internal.MerkleRoot[] calldata merkleRoots, Signature[] calldata signatures ) external view { if (s_configCount == 0) { revert ConfigNotSet(); } if (signatures.length < s_config.fSign + 1) revert ThresholdNotMet(); bytes32 digest = keccak256( abi.encode( RMN_V1_6_ANY2EVM_REPORT, Report({ destChainId: block.chainid, destChainSelector: i_localChainSelector, rmnRemoteContractAddress: address(this), offrampAddress: offRampAddress, rmnHomeContractConfigDigest: s_config.rmnHomeContractConfigDigest, merkleRoots: merkleRoots }) ) ); address prevAddress; address signerAddress; for (uint256 i = 0; i < signatures.length; ++i) { signerAddress = ecrecover(digest, ECDSA_RECOVERY_V, signatures[i].r, signatures[i].s); if (signerAddress == address(0)) revert InvalidSignature(); if (prevAddress >= signerAddress) revert OutOfOrderSignatures(); if (!s_signers[signerAddress]) revert UnexpectedSigner(); prevAddress = signerAddress; } } // ================================================================ // │ Config │ // ================================================================ /// @notice Sets the configuration of the contract. /// @param newConfig the new configuration. /// @dev setting config is atomic; we delete all pre-existing config and set everything from scratch. function setConfig( Config calldata newConfig ) external onlyOwner { if (newConfig.rmnHomeContractConfigDigest == bytes32(0)) { revert ZeroValueNotAllowed(); } // signers are in ascending order of nodeIndex. for (uint256 i = 1; i < newConfig.signers.length; ++i) { if (!(newConfig.signers[i - 1].nodeIndex < newConfig.signers[i].nodeIndex)) { revert InvalidSignerOrder(); } } // min signers requirement is tenable. if (newConfig.signers.length < 2 * newConfig.fSign + 1) { revert NotEnoughSigners(); } // clear the old signers. for (uint256 i = s_config.signers.length; i > 0; --i) { delete s_signers[s_config.signers[i - 1].onchainPublicKey]; } // set the new signers. for (uint256 i = 0; i < newConfig.signers.length; ++i) { if (s_signers[newConfig.signers[i].onchainPublicKey]) { revert DuplicateOnchainPublicKey(); } s_signers[newConfig.signers[i].onchainPublicKey] = true; } s_config = newConfig; uint32 newConfigCount = ++s_configCount; emit ConfigSet(newConfigCount, newConfig); } /// @notice Returns the current configuration of the contract and a version number. /// @return version the current configs version. /// @return config the current config. function getVersionedConfig() external view returns (uint32 version, Config memory config) { return (s_configCount, s_config); } /// @notice Returns the chain selector configured at deployment time. /// @return localChainSelector the chain selector, not the chain ID. function getLocalChainSelector() external view returns (uint64 localChainSelector) { return i_localChainSelector; } /// @notice Returns the 32 byte header used in computing the report digest. /// @return digestHeader the digest header. function getReportDigestHeader() external pure returns (bytes32 digestHeader) { return RMN_V1_6_ANY2EVM_REPORT; } // ================================================================ // │ Cursing │ // ================================================================ /// @notice Curse a single subject. /// @param subject the subject to curse. function curse( bytes16 subject ) external { bytes16[] memory subjects = new bytes16[](1); subjects[0] = subject; curse(subjects); } /// @notice Curse an array of subjects. /// @param subjects the subjects to curse. /// @dev reverts if any of the subjects are already cursed or if there is a duplicate. function curse( bytes16[] memory subjects ) public onlyOwner { for (uint256 i = 0; i < subjects.length; ++i) { if (!s_cursedSubjects.add(subjects[i])) { revert AlreadyCursed(subjects[i]); } } emit Cursed(subjects); } /// @notice Uncurse a single subject. /// @param subject the subject to uncurse. function uncurse( bytes16 subject ) external { bytes16[] memory subjects = new bytes16[](1); subjects[0] = subject; uncurse(subjects); } /// @notice Uncurse an array of subjects. /// @param subjects the subjects to uncurse. /// @dev reverts if any of the subjects are not cursed or if there is a duplicate. function uncurse( bytes16[] memory subjects ) public onlyOwner { for (uint256 i = 0; i < subjects.length; ++i) { if (!s_cursedSubjects.remove(subjects[i])) { revert NotCursed(subjects[i]); } } emit Uncursed(subjects); } /// @inheritdoc IRMNRemote function getCursedSubjects() external view returns (bytes16[] memory subjects) { return s_cursedSubjects.values(); } /// @inheritdoc IRMNRemote function isCursed() external view override(IRMN, IRMNRemote) returns (bool) { // There are zero curses under normal circumstances, which means it's cheaper to check for the absence of curses. // than to check the subject list for the global curse subject. if (s_cursedSubjects.length() == 0) { return false; } return s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); } /// @inheritdoc IRMNRemote function isCursed( bytes16 subject ) external view override(IRMN, IRMNRemote) returns (bool) { // There are zero curses under normal circumstances, which means it's cheaper to check for the absence of curses. // than to check the subject list twice, as we have to check for both the given and global curse subjects. if (s_cursedSubjects.length() == 0) { return false; } return s_cursedSubjects.contains(subject) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); } // ================================================================ // │ Legacy pass through │ // ================================================================ /// @inheritdoc IRMN /// @dev This function is only expected to be used for messages from CCIP versions below 1.6. function isBlessed( TaggedRoot calldata taggedRoot ) external view returns (bool) { if (i_legacyRMN == IRMN(address(0))) { revert IsBlessedNotAvailable(); } return i_legacyRMN.isBlessed(taggedRoot); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. interface IRMN { /// @notice A Merkle root tagged with the address of the commit store contract it is destined for. struct TaggedRoot { address commitStore; bytes32 root; } /// @notice Callers MUST NOT cache the return value as a blessed tagged root could become unblessed. function isBlessed( TaggedRoot calldata taggedRoot ) external view returns (bool); /// @notice Iff there is an active global or legacy curse, this function returns true. function isCursed() external view returns (bool); /// @notice Iff there is an active global curse, or an active curse for `subject`, this function returns true. /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). function isCursed( bytes16 subject ) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {Internal} from "../libraries/Internal.sol"; /// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. interface IRMNRemote { /// @notice signature components from RMN nodes. struct Signature { bytes32 r; bytes32 s; } /// @notice Verifies signatures of RMN nodes, on dest lane updates as provided in the CommitReport. /// @param offRampAddress is not inferred by msg.sender, in case the call is made through RMNProxy. /// @param merkleRoots must be well formed, and is a representation of the CommitReport received from the oracles. /// @param signatures rmnNodes ECDSA sigs, only r & s, must be sorted in ascending order by signer address. /// @dev Will revert if verification fails. function verify( address offRampAddress, Internal.MerkleRoot[] memory merkleRoots, Signature[] memory signatures ) external view; /// @notice gets the current set of cursed subjects. /// @return subjects the list of cursed subjects. function getCursedSubjects() external view returns (bytes16[] memory subjects); /// @notice If there is an active global or legacy curse, this function returns true. /// @return bool true if there is an active global curse. function isCursed() external view returns (bool); /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). /// @return bool true if the provided subject is cured *or* if there is an active global curse. function isCursed( bytes16 subject ) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {MerkleMultiProof} from "../libraries/MerkleMultiProof.sol"; /// @notice Library for CCIP internal definitions common to multiple contracts. /// @dev The following is a non-exhaustive list of "known issues" for CCIP: /// - We could implement yield claiming for Blast. This is not worth the custom code path on non-blast chains. /// - uint32 is used for timestamps, which will overflow in 2106. This is not a concern for the current use case, as we /// expect to have migrated to a new version by then. library Internal { error InvalidEVMAddress(bytes encodedAddress); error Invalid32ByteAddress(bytes encodedAddress); /// @dev We limit return data to a selector plus 4 words. This is to avoid malicious contracts from returning /// large amounts of data and causing repeated out-of-gas scenarios. uint16 internal constant MAX_RET_BYTES = 4 + 4 * 32; /// @dev The expected number of bytes returned by the balanceOf function. uint256 internal constant MAX_BALANCE_OF_RET_BYTES = 32; /// @dev The address used to send calls for gas estimation. /// You only need to use this address if the minimum gas limit specified by the user is not actually enough to execute the /// given message and you're attempting to estimate the actual necessary gas limit address public constant GAS_ESTIMATION_SENDER = address(0xC11C11C11C11C11C11C11C11C11C11C11C11C1); /// @notice A collection of token price and gas price updates. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct PriceUpdates { TokenPriceUpdate[] tokenPriceUpdates; GasPriceUpdate[] gasPriceUpdates; } /// @notice Token price in USD. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct TokenPriceUpdate { address sourceToken; // Source token. uint224 usdPerToken; // 1e18 USD per 1e18 of the smallest token denomination. } /// @notice Gas price for a given chain in USD, its value may contain tightly packed fields. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct GasPriceUpdate { uint64 destChainSelector; // Destination chain selector. uint224 usdPerUnitGas; // 1e18 USD per smallest unit (e.g. wei) of destination chain gas. } /// @notice A timestamped uint224 value that can contain several tightly packed fields. struct TimestampedPackedUint224 { uint224 value; // ────╮ Value in uint224, packed. uint32 timestamp; // ─╯ Timestamp of the most recent price update. } /// @dev Gas price is stored in 112-bit unsigned int. uint224 can pack 2 prices. /// When packing L1 and L2 gas prices, L1 gas price is left-shifted to the higher-order bits. /// Using uint8 type, which cannot be higher than other bit shift operands, to avoid shift operand type warning. uint8 public constant GAS_PRICE_BITS = 112; struct SourceTokenData { // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be // relied upon by the destination pool to validate the source pool. bytes sourcePoolAddress; // The address of the destination token, abi encoded in the case of EVM chains. // This value is UNTRUSTED as any pool owner can return whatever value they want. bytes destTokenAddress; // Optional pool data to be transferred to the destination chain. Be default this is capped at // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead // has to be set for the specific token. bytes extraData; uint32 destGasAmount; // The amount of gas available for the releaseOrMint and balanceOf calls on the offRamp } /// @notice Report that is submitted by the execution DON at the execution phase, including chain selector data. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct ExecutionReport { uint64 sourceChainSelector; // Source chain selector for which the report is submitted. Any2EVMRampMessage[] messages; // Contains a bytes array for each message, each inner bytes array contains bytes per transferred token. bytes[][] offchainTokenData; bytes32[] proofs; uint256 proofFlagBits; } /// @dev Any2EVMRampMessage struct has 10 fields, including 3 variable unnested arrays, sender, data and tokenAmounts. /// Each variable array takes 1 more slot to store its length. /// When abi encoded, excluding array contents, Any2EVMMessage takes up a fixed number of 13 slots, 32 bytes each. /// Assume 1 slot for sender /// For structs that contain arrays, 1 more slot is added to the front, reaching a total of 14. /// The fixed bytes does not cover struct data (this is represented by MESSAGE_FIXED_BYTES_PER_TOKEN) uint256 public constant MESSAGE_FIXED_BYTES = 32 * 15; /// @dev Any2EVMTokensTransfer struct bytes length /// 0x20 /// sourcePoolAddress_offset /// destTokenAddress /// destGasAmount /// extraData_offset /// amount /// sourcePoolAddress_length /// sourcePoolAddress_content // assume 1 slot /// extraData_length // contents billed separately uint256 public constant MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * (4 + (3 + 2)); bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1"); bytes32 internal constant EVM_2_ANY_MESSAGE_HASH = keccak256("EVM2AnyMessageHashV1"); /// @dev Used to hash messages for multi-lane family-agnostic OffRamps. /// OnRamp hash(EVM2AnyMessage) != Any2EVMRampMessage.messageId. /// OnRamp hash(EVM2AnyMessage) != OffRamp hash(Any2EVMRampMessage). /// @param original OffRamp message to hash. /// @param metadataHash Hash preimage to ensure global uniqueness. /// @return hashedMessage hashed message as a keccak256. function _hash(Any2EVMRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { // Fixed-size message fields are included in nested hash to reduce stack pressure. // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. return keccak256( abi.encode( MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, metadataHash, keccak256( abi.encode( original.header.messageId, original.receiver, original.header.sequenceNumber, original.gasLimit, original.header.nonce ) ), keccak256(original.sender), keccak256(original.data), keccak256(abi.encode(original.tokenAmounts)) ) ); } function _hash(EVM2AnyRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { // Fixed-size message fields are included in nested hash to reduce stack pressure. // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. return keccak256( abi.encode( MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, metadataHash, keccak256( abi.encode( original.sender, original.header.sequenceNumber, original.header.nonce, original.feeToken, original.feeTokenAmount ) ), keccak256(original.receiver), keccak256(original.data), keccak256(abi.encode(original.tokenAmounts)), keccak256(original.extraArgs) ) ); } /// @dev We disallow the first 1024 addresses to avoid calling into a range known for hosting precompiles. Calling /// into precompiles probably won't cause any issues, but to be safe we can disallow this range. It is extremely /// unlikely that anyone would ever be able to generate an address in this range. There is no official range of /// precompiles, but EIP-7587 proposes to reserve the range 0x100 to 0x1ff. Our range is more conservative, even /// though it might not be exhaustive for all chains, which is OK. We also disallow the zero address, which is a /// common practice. uint256 public constant EVM_PRECOMPILE_SPACE = 1024; // According to the Aptos docs, the first 0xa addresses are reserved for precompiles. // https://github.com/aptos-labs/aptos-core/blob/main/aptos-move/framework/aptos-framework/doc/account.md#function-create_framework_reserved_account-1 uint256 public constant APTOS_PRECOMPILE_SPACE = 0x0b; /// @notice This methods provides validation for parsing abi encoded addresses by ensuring the address is within the /// EVM address space. If it isn't it will revert with an InvalidEVMAddress error, which we can catch and handle /// more gracefully than a revert from abi.decode. function _validateEVMAddress( bytes memory encodedAddress ) internal pure { if (encodedAddress.length != 32) revert InvalidEVMAddress(encodedAddress); uint256 encodedAddressUint = abi.decode(encodedAddress, (uint256)); if (encodedAddressUint > type(uint160).max || encodedAddressUint < EVM_PRECOMPILE_SPACE) { revert InvalidEVMAddress(encodedAddress); } } /// @notice This methods provides validation for parsing abi encoded addresses by ensuring the address is within the /// bounds of [minValue, uint256.max]. If it isn't it will revert with an Invalid32ByteAddress error. function _validate32ByteAddress(bytes memory encodedAddress, uint256 minValue) internal pure { if (encodedAddress.length != 32) revert Invalid32ByteAddress(encodedAddress); if (minValue > 0) { if (abi.decode(encodedAddress, (uint256)) < minValue) { revert Invalid32ByteAddress(encodedAddress); } } } /// @notice Enum listing the possible message execution states within the offRamp contract. /// UNTOUCHED never executed. /// IN_PROGRESS currently being executed, used a replay protection. /// SUCCESS successfully executed. End state. /// FAILURE unsuccessfully executed, manual execution is now enabled. /// @dev RMN depends on this enum, if changing, please notify the RMN maintainers. enum MessageExecutionState { UNTOUCHED, IN_PROGRESS, SUCCESS, FAILURE } /// @notice CCIP OCR plugin type, used to separate execution & commit transmissions and configs. enum OCRPluginType { Commit, Execution } /// @notice Family-agnostic header for OnRamp & OffRamp messages. /// The messageId is not expected to match hash(message), since it may originate from another ramp family. struct RampMessageHeader { bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded). uint64 sourceChainSelector; // ─╮ the chain selector of the source chain, note: not chainId. uint64 destChainSelector; // │ the chain selector of the destination chain, note: not chainId. uint64 sequenceNumber; // │ sequence number, not unique across lanes. uint64 nonce; // ───────────────╯ nonce for this lane for this sender, not unique across senders/lanes. } struct EVM2AnyTokenTransfer { // The source pool EVM address. This value is trusted as it was obtained through the onRamp. It can be relied // upon by the destination pool to validate the source pool. address sourcePoolAddress; // The EVM address of the destination token. // This value is UNTRUSTED as any pool owner can return whatever value they want. bytes destTokenAddress; // Optional pool data to be transferred to the destination chain. Be default this is capped at // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead // has to be set for the specific token. bytes extraData; uint256 amount; // Amount of tokens. // Destination chain data used to execute the token transfer on the destination chain. For an EVM destination, it // consists of the amount of gas available for the releaseOrMint and transfer calls made by the offRamp. bytes destExecData; } struct Any2EVMTokenTransfer { // The source pool EVM address encoded to bytes. This value is trusted as it is obtained through the onRamp. It can // be relied upon by the destination pool to validate the source pool. bytes sourcePoolAddress; address destTokenAddress; // ─╮ Address of destination token uint32 destGasAmount; // ─────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. // Optional pool data to be transferred to the destination chain. Be default this is capped at // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead // has to be set for the specific token. bytes extraData; uint256 amount; // Amount of tokens. } /// @notice Family-agnostic message routed to an OffRamp. /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage), hash(Any2EVMRampMessage) != messageId due to encoding /// and parameter differences. struct Any2EVMRampMessage { RampMessageHeader header; // Message header. bytes sender; // sender address on the source chain. bytes data; // arbitrary data payload supplied by the message sender. address receiver; // receiver address on the destination chain. uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution. Any2EVMTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer. } /// @notice Family-agnostic message emitted from the OnRamp. /// Note: hash(Any2EVMRampMessage) != hash(EVM2AnyRampMessage) due to encoding & parameter differences. /// messageId = hash(EVM2AnyRampMessage) using the source EVM chain's encoding format. struct EVM2AnyRampMessage { RampMessageHeader header; // Message header. address sender; // sender address on the source chain. bytes data; // arbitrary data payload supplied by the message sender. bytes receiver; // receiver address on the destination chain. bytes extraArgs; // destination-chain specific extra args, such as the gasLimit for EVM chains. address feeToken; // fee token. uint256 feeTokenAmount; // fee token amount. uint256 feeValueJuels; // fee amount in Juels. EVM2AnyTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer. } // bytes4(keccak256("CCIP ChainFamilySelector EVM")); bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; // bytes4(keccak256("CCIP ChainFamilySelector SVM")); bytes4 public constant CHAIN_FAMILY_SELECTOR_SVM = 0x1e10bdc4; // bytes4(keccak256("CCIP ChainFamilySelector APTOS")); bytes4 public constant CHAIN_FAMILY_SELECTOR_APTOS = 0xac77ffec; /// @dev Holds a merkle root and interval for a source chain so that an array of these can be passed in the CommitReport. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. /// @dev inefficient struct packing intentionally chosen to maintain order of specificity. Not a storage struct so impact is minimal. // solhint-disable-next-line gas-struct-packing struct MerkleRoot { uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to bytes onRampAddress; // Generic onRamp address, to support arbitrary sources; for EVM, use abi.encode uint64 minSeqNr; // ─────────╮ Minimum sequence number, inclusive uint64 maxSeqNr; // ─────────╯ Maximum sequence number, inclusive bytes32 merkleRoot; // Merkle root covering the interval & source chain messages } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.4; library MerkleMultiProof { /// @notice Leaf domain separator, should be used as the first 32 bytes of a leaf's preimage. bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000; /// @notice Internal domain separator, should be used as the first 32 bytes of an internal node's preimage. bytes32 internal constant INTERNAL_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000001; uint256 internal constant MAX_NUM_HASHES = 256; error InvalidProof(); error LeavesCannotBeEmpty(); /// @notice Computes the root based on provided pre-hashed leaf nodes in leaves, internal nodes in proofs, and using /// proofFlagBits' i-th bit to determine if an element of proofs or one of the previously computed leafs or internal /// nodes will be used for the i-th hash. /// @param leaves Should be pre-hashed and the first 32 bytes of a leaf's preimage should match LEAF_DOMAIN_SEPARATOR. /// @param proofs Hashes to be used instead of a leaf hash when the proofFlagBits indicates a proof should be used. /// @param proofFlagBits A single uint256 of which each bit indicates whether a leaf or a proof needs to be used in /// a hash operation. /// @dev the maximum number of hash operations it set to 256. Any input that would require more than 256 hashes to get /// to a root will revert. /// @dev For given input `leaves` = [a,b,c] `proofs` = [D] and `proofFlagBits` = 5 /// totalHashes = 3 + 1 - 1 = 3 /// ** round 1 ** /// proofFlagBits = (5 >> 0) & 1 = true /// hashes[0] = hashPair(a, b) /// (leafPos, hashPos, proofPos) = (2, 0, 0); /// /// ** round 2 ** /// proofFlagBits = (5 >> 1) & 1 = false /// hashes[1] = hashPair(D, c) /// (leafPos, hashPos, proofPos) = (3, 0, 1); /// /// ** round 3 ** /// proofFlagBits = (5 >> 2) & 1 = true /// hashes[2] = hashPair(hashes[0], hashes[1]) /// (leafPos, hashPos, proofPos) = (3, 2, 1); /// /// i = 3 and no longer < totalHashes. The algorithm is done /// return hashes[totalHashes - 1] = hashes[2]; the last hash we computed. // We mark this function as internal to force it to be inlined in contracts that use it, but semantically it is public. function _merkleRoot( bytes32[] memory leaves, bytes32[] memory proofs, uint256 proofFlagBits ) internal pure returns (bytes32) { unchecked { uint256 leavesLen = leaves.length; uint256 proofsLen = proofs.length; if (leavesLen == 0) revert LeavesCannotBeEmpty(); if (!(leavesLen <= MAX_NUM_HASHES + 1 && proofsLen <= MAX_NUM_HASHES + 1)) revert InvalidProof(); uint256 totalHashes = leavesLen + proofsLen - 1; if (!(totalHashes <= MAX_NUM_HASHES)) revert InvalidProof(); if (totalHashes == 0) { return leaves[0]; } bytes32[] memory hashes = new bytes32[](totalHashes); (uint256 leafPos, uint256 hashPos, uint256 proofPos) = (0, 0, 0); for (uint256 i = 0; i < totalHashes; ++i) { // Checks if the bit flag signals the use of a supplied proof or a leaf/previous hash. bytes32 a; if (proofFlagBits & (1 << i) == (1 << i)) { // Use a leaf or a previously computed hash. if (leafPos < leavesLen) { a = leaves[leafPos++]; } else { a = hashes[hashPos++]; } } else { // Use a supplied proof. a = proofs[proofPos++]; } // The second part of the hashed pair is never a proof as hashing two proofs would result in a // hash that can already be computed offchain. bytes32 b; if (leafPos < leavesLen) { b = leaves[leafPos++]; } else { b = hashes[hashPos++]; } if (!(hashPos <= i)) revert InvalidProof(); hashes[i] = _hashPair(a, b); } if (!(hashPos == totalHashes - 1 && leafPos == leavesLen && proofPos == proofsLen)) revert InvalidProof(); // Return the last hash. return hashes[totalHashes - 1]; } } /// @notice Hashes two bytes32 objects in their given order, prepended by the INTERNAL_DOMAIN_SEPARATOR. function _hashInternalNode(bytes32 left, bytes32 right) private pure returns (bytes32 hash) { return keccak256(abi.encode(INTERNAL_DOMAIN_SEPARATOR, left, right)); } /// @notice Hashes two bytes32 objects. The order is taken into account, using the lower value first. function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _hashInternalNode(a, b) : _hashInternalNode(b, a); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {IOwnable} from "../interfaces/IOwnable.sol"; /// @notice A minimal contract that implements 2-step ownership transfer and nothing more. It's made to be minimal /// to reduce the impact of the bytecode size on any contract that inherits from it. contract Ownable2Step is IOwnable { /// @notice The pending owner is the address to which ownership may be transferred. address private s_pendingOwner; /// @notice The owner is the current owner of the contract. /// @dev The owner is the second storage variable so any implementing contract could pack other state with it /// instead of the much less used s_pendingOwner. address private s_owner; error OwnerCannotBeZero(); error MustBeProposedOwner(); error CannotTransferToSelf(); error OnlyCallableByOwner(); event OwnershipTransferRequested(address indexed from, address indexed to); event OwnershipTransferred(address indexed from, address indexed to); constructor(address newOwner, address pendingOwner) { if (newOwner == address(0)) { revert OwnerCannotBeZero(); } s_owner = newOwner; if (pendingOwner != address(0)) { _transferOwnership(pendingOwner); } } /// @notice Get the current owner function owner() public view override returns (address) { return s_owner; } /// @notice Allows an owner to begin transferring ownership to a new address. The new owner needs to call /// `acceptOwnership` to accept the transfer before any permissions are changed. /// @param to The address to which ownership will be transferred. function transferOwnership(address to) public override onlyOwner { _transferOwnership(to); } /// @notice validate, transfer ownership, and emit relevant events /// @param to The address to which ownership will be transferred. function _transferOwnership(address to) private { if (to == msg.sender) { revert CannotTransferToSelf(); } s_pendingOwner = to; emit OwnershipTransferRequested(s_owner, to); } /// @notice Allows an ownership transfer to be completed by the recipient. function acceptOwnership() external override { if (msg.sender != s_pendingOwner) { revert MustBeProposedOwner(); } address oldOwner = s_owner; s_owner = msg.sender; s_pendingOwner = address(0); emit OwnershipTransferred(oldOwner, msg.sender); } /// @notice validate access function _validateOwnership() internal view { if (msg.sender != s_owner) { revert OnlyCallableByOwner(); } } /// @notice Reverts if called by anyone other than the contract owner. modifier onlyOwner() { _validateOwnership(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {Ownable2Step} from "./Ownable2Step.sol"; /// @notice Sets the msg.sender to be the owner of the contract and does not set a pending owner. contract Ownable2StepMsgSender is Ownable2Step { constructor() Ownable2Step(msg.sender, address(0)) {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. /// @dev this is a fully copy of OZ's EnumerableSet library with the addition of a Bytes16Set pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // Bytes16Set struct Bytes16Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes16Set storage set, bytes16 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes16Set storage set, bytes16 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes16Set storage set, bytes16 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes16Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes16Set storage set, uint256 index) internal view returns (bytes16) { return bytes16(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes16Set storage set) internal view returns (bytes16[] memory) { bytes32[] memory store = _values(set._inner); bytes16[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IOwnable { function owner() external returns (address); function transferOwnership(address recipient) external; function acceptOwnership() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ITypeAndVersion { function typeAndVersion() external pure returns (string memory); }
{ "evmVersion": "paris", "libraries": {}, "metadata": { "appendCBOR": true, "bytecodeHash": "none", "useLiteralContent": false }, "optimizer": { "enabled": true, "runs": 80000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "remappings": [ "forge-std/=node_modules/@chainlink/contracts/src/v0.8/vendor/forge-std/src/", "@chainlink/=node_modules/@chainlink/contracts/src/v0.8/" ], "viaIR": true }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint64","name":"localChainSelector","type":"uint64"},{"internalType":"contract IRMN","name":"legacyRMN","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"AlreadyCursed","type":"error"},{"inputs":[],"name":"CannotTransferToSelf","type":"error"},{"inputs":[],"name":"ConfigNotSet","type":"error"},{"inputs":[],"name":"DuplicateOnchainPublicKey","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSignerOrder","type":"error"},{"inputs":[],"name":"IsBlessedNotAvailable","type":"error"},{"inputs":[],"name":"MustBeProposedOwner","type":"error"},{"inputs":[{"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"NotCursed","type":"error"},{"inputs":[],"name":"NotEnoughSigners","type":"error"},{"inputs":[],"name":"OnlyCallableByOwner","type":"error"},{"inputs":[],"name":"OutOfOrderSignatures","type":"error"},{"inputs":[],"name":"OwnerCannotBeZero","type":"error"},{"inputs":[],"name":"ThresholdNotMet","type":"error"},{"inputs":[],"name":"UnexpectedSigner","type":"error"},{"inputs":[],"name":"ZeroValueNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"version","type":"uint32"},{"components":[{"internalType":"bytes32","name":"rmnHomeContractConfigDigest","type":"bytes32"},{"components":[{"internalType":"address","name":"onchainPublicKey","type":"address"},{"internalType":"uint64","name":"nodeIndex","type":"uint64"}],"internalType":"struct RMNRemote.Signer[]","name":"signers","type":"tuple[]"},{"internalType":"uint64","name":"fSign","type":"uint64"}],"indexed":false,"internalType":"struct RMNRemote.Config","name":"config","type":"tuple"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes16[]","name":"subjects","type":"bytes16[]"}],"name":"Cursed","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":"bytes16[]","name":"subjects","type":"bytes16[]"}],"name":"Uncursed","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"curse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes16[]","name":"subjects","type":"bytes16[]"}],"name":"curse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCursedSubjects","outputs":[{"internalType":"bytes16[]","name":"subjects","type":"bytes16[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLocalChainSelector","outputs":[{"internalType":"uint64","name":"localChainSelector","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReportDigestHeader","outputs":[{"internalType":"bytes32","name":"digestHeader","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getVersionedConfig","outputs":[{"internalType":"uint32","name":"version","type":"uint32"},{"components":[{"internalType":"bytes32","name":"rmnHomeContractConfigDigest","type":"bytes32"},{"components":[{"internalType":"address","name":"onchainPublicKey","type":"address"},{"internalType":"uint64","name":"nodeIndex","type":"uint64"}],"internalType":"struct RMNRemote.Signer[]","name":"signers","type":"tuple[]"},{"internalType":"uint64","name":"fSign","type":"uint64"}],"internalType":"struct RMNRemote.Config","name":"config","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"commitStore","type":"address"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct IRMN.TaggedRoot","name":"taggedRoot","type":"tuple"}],"name":"isBlessed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"isCursed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCursed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"rmnHomeContractConfigDigest","type":"bytes32"},{"components":[{"internalType":"address","name":"onchainPublicKey","type":"address"},{"internalType":"uint64","name":"nodeIndex","type":"uint64"}],"internalType":"struct RMNRemote.Signer[]","name":"signers","type":"tuple[]"},{"internalType":"uint64","name":"fSign","type":"uint64"}],"internalType":"struct RMNRemote.Config","name":"newConfig","type":"tuple"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes16","name":"subject","type":"bytes16"}],"name":"uncurse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes16[]","name":"subjects","type":"bytes16[]"}],"name":"uncurse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"offRampAddress","type":"address"},{"components":[{"internalType":"uint64","name":"sourceChainSelector","type":"uint64"},{"internalType":"bytes","name":"onRampAddress","type":"bytes"},{"internalType":"uint64","name":"minSeqNr","type":"uint64"},{"internalType":"uint64","name":"maxSeqNr","type":"uint64"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct Internal.MerkleRoot[]","name":"merkleRoots","type":"tuple[]"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct IRMNRemote.Signature[]","name":"signatures","type":"tuple[]"}],"name":"verify","outputs":[],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c0346100d357601f6121f938819003918201601f19168301916001600160401b038311848410176100d85780849260409485528339810103126100d35780516001600160401b038116918282036100d35760200151916001600160a01b03831683036100d35733156100c257600180546001600160a01b03191633179055156100b15760805260a05260405161210a90816100ef82396080518181816102fe0152610712015260a05181610f7d0152f35b63273e150360e21b60005260046000fd5b639b15e16f60e01b60005260046000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b60003560e01c8063181f5a77146119ce578063198f0f77146112df5780631add205f146111145780632cbc26bb146110d3578063397796f7146110905780634d61677114610f3557806362eed41514610e155780636509a95414610dbc5780636d2d399314610c9c57806370a9089e146105f057806379ba5097146105075780638da5cb5b146104b55780639a19b329146103c7578063d881e09214610322578063eaa83ddd146102bf578063f2fde38b146101cf5763f8bb876e146100d757600080fd5b346101ca576100e536611b71565b6100ed611ec2565b60005b81518110156101955761012e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b51166120a3565b1561013b576001016100f0565b610166907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f19d5c79b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b0390a1005b600080fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5773ffffffffffffffffffffffffffffffffffffffff61021b611b36565b610223611ec2565b1633811461029557807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602060405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760405180602060065491828152019060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f9060005b8181106103b1576103ad856103a181870382611a67565b60405191829182611c38565b0390f35b825484526020909301926001928301920161038a565b346101ca576103d536611b71565b6103dd611ec2565b60005b81518110156104855761041e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b5116611f0d565b1561042b576001016103e0565b610456907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f73281fa10000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760005473ffffffffffffffffffffffffffffffffffffffff811633036105c6577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610627611b36565b67ffffffffffffffff602435116101ca573660236024350112156101ca57602435600401359067ffffffffffffffff82116101ca573660248360051b81350101116101ca576044359067ffffffffffffffff82116101ca57366023830112156101ca5767ffffffffffffffff8260040135116101ca57366024836004013560061b840101116101ca5763ffffffff6005541615610c725767ffffffffffffffff6106d48160045416611d3c565b16826004013510610c485760025460405160c0810181811067ffffffffffffffff821117610c1957604052468152602081019267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168452604082019230845273ffffffffffffffffffffffffffffffffffffffff60608401921682526080830190815261076987611b59565b916107776040519384611a67565b8783526000976024803501602085015b60248360051b813501018210610a61575050509073ffffffffffffffffffffffffffffffffffffffff8095939260a0860193845260405196879567ffffffffffffffff602088019a7f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538c526040808a01526101208901995160608a015251166080880152511660a0860152511660c08401525160e08301525160c0610100830152805180935261014082019260206101408260051b85010192019388905b8282106109c8575050506108809250037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611a67565b5190208290815b83600401358310610896578480f35b60208560806108ad86886004013560248a01611ce8565b35836108c1888a6004013560248c01611ce8565b013560405191878352601b868401526040830152606082015282805260015afa156109bd5784519073ffffffffffffffffffffffffffffffffffffffff82169081156109955773ffffffffffffffffffffffffffffffffffffffff829116101561096d578552600860205260ff604086205416156109455760019290920191610887565b6004857faaaa9141000000000000000000000000000000000000000000000000000000008152fd5b6004867fbbe15e7f000000000000000000000000000000000000000000000000000000008152fd5b6004877f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d86823e3d90fd5b91936020847ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec08293600195970301855287519067ffffffffffffffff8251168152608080610a238585015160a08786015260a0850190611aa8565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff606082015116606085015201519101529601920192018593919492610845565b81359067ffffffffffffffff8211610c155760a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc836024350136030112610c15576040519060a0820182811067ffffffffffffffff821117610be457604052610ad060248481350101611d95565b82526044836024350101359167ffffffffffffffff8311610c115736604360243586018501011215610c115767ffffffffffffffff6024848682350101013511610be457908d9160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6024878982350101013501160193610b576040519586611a67565b60248035870182019081013580875236910160440111610be057602495602095869560a49387908a90813586018101808301359060440186850137858235010101358301015285840152610bb060648289350101611d95565b6040840152610bc460848289350101611d95565b6060840152863501013560808201528152019201919050610787565b8380fd5b60248e7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8d80fd5b8b80fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f59fa4a930000000000000000000000000000000000000000000000000000000060005260046000fd5b7face124bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610cd3611b07565b604090815190610ce38383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610d3a83611ea1565b91169052610d46611ec2565b60005b8151811015610d8d57610d807fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b1561042b57600101610d49565b82517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610e4c611b07565b604090815190610e5c8383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610eb383611ea1565b91169052610ebf611ec2565b60005b8151811015610f0657610ef97fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b1561013b57600101610ec2565b82517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b346101ca5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57600073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168015611068576020604491604051928380927f4d61677100000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff610fef611b36565b16600483015260243560248301525afa90811561105d57829161101a575b6020826040519015158152f35b90506020813d602011611055575b8161103560209383611a67565b810103126110515751801515810361105157602091508261100d565b5080fd5b3d9150611028565b6040513d84823e3d90fd5b6004827f0a7c4edd000000000000000000000000000000000000000000000000000000008152fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c9611e44565b6040519015158152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c961110f611b07565b611daa565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760006040805161115281611a4b565b82815260606020820152015263ffffffff600554166040519061117482611a4b565b60025482526003549161118683611b59565b926111946040519485611a67565b808452600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9190602086015b82821061128057505050506020810192835267ffffffffffffffff6004541692604082019384526040519283526040602084015260a083019151604084015251906060808401528151809152602060c0840192019060005b81811061123e5750505067ffffffffffffffff8293511660808301520390f35b8251805173ffffffffffffffffffffffffffffffffffffffff16855260209081015167ffffffffffffffff16818601526040909401939092019160010161121e565b6040516040810181811067ffffffffffffffff821117610c1957600192839260209260405267ffffffffffffffff885473ffffffffffffffffffffffffffffffffffffffff8116835260a01c16838201528152019401910190926111c6565b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760043567ffffffffffffffff81116101ca57806004018136039160607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8401126101ca5761135a611ec2565b81359081156119a457909260248201919060015b6113788486611c94565b90508110156114595761138b8486611c94565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019183831161142a576113cc926020926113c692611ce8565b01611d27565b67ffffffffffffffff806113ef60206113c6866113e98b8d611c94565b90611ce8565b16911610156114005760010161136e565b7f448515170000000000000000000000000000000000000000000000000000000060005260046000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b508390856114678584611c94565b60448601915061147682611d27565b60011b6801fffffffffffffffe67fffffffffffffffe82169116810361142a576114a867ffffffffffffffff91611d3c565b161161197a57600354805b611877575060005b6114c58786611c94565b905081101561159e5773ffffffffffffffffffffffffffffffffffffffff6114f96114f4836113e98b8a611c94565b611d74565b16600052600860205260ff60406000205416611574578073ffffffffffffffffffffffffffffffffffffffff6115386114f46001946113e98c8b611c94565b1660005260086020526040600020827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055016114bb565b7f28cae27d0000000000000000000000000000000000000000000000000000000060005260046000fd5b50846115b08780959685600255611c94565b90680100000000000000008211610c195760035482600355808310611831575b50600360005260206000206000915b838310611783575050505067ffffffffffffffff6115fc83611d27565b167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000060045416176004556005549463ffffffff86169563ffffffff871461142a5763ffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000098011696879116176005557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd6040519560208752608087019560208801523591018112156101ca57016024600482013591019267ffffffffffffffff82116101ca578160061b360384136101ca578190606060408701525260a0840192906000905b80821061173057867f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c87808867ffffffffffffffff6117258a611d95565b1660608301520390a2005b90919384359073ffffffffffffffffffffffffffffffffffffffff82168092036101ca5760408160019382935267ffffffffffffffff61177260208a01611d95565b1660208201520195019201906116e7565b600160408273ffffffffffffffffffffffffffffffffffffffff6117a78495611d74565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008654161785556117db60208201611d27565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff000000000000000000000000000000000000000087549260a01b169116178555019201920191906115df565b60036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9081019083015b81811061186b57506115d0565b6000815560010161185e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600090600354111561194d57600390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85a81015473ffffffffffffffffffffffffffffffffffffffff16600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055801561142a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01806114b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b7f014c50200000000000000000000000000000000000000000000000000000000060005260046000fd5b7f9cf8540c0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca576103ad6040805190611a0f8183611a67565b600f82527f524d4e52656d6f746520312e362e300000000000000000000000000000000000602083015251918291602083526020830190611aa8565b6060810190811067ffffffffffffffff821117610c1957604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610c1957604052565b919082519283825260005b848110611af25750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201611ab3565b600435907fffffffffffffffffffffffffffffffff00000000000000000000000000000000821682036101ca57565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101ca57565b67ffffffffffffffff8111610c195760051b60200190565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101ca576004359067ffffffffffffffff82116101ca57806023830112156101ca57816004013590611bc882611b59565b92611bd66040519485611a67565b8284526024602085019360051b8201019182116101ca57602401915b818310611bff5750505090565b82357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681036101ca57815260209283019201611bf2565b602060408183019282815284518094520192019060005b818110611c5c5750505090565b82517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016845260209384019390920191600101611c4f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ca570180359067ffffffffffffffff82116101ca57602001918160061b360383136101ca57565b9190811015611cf85760061b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff811681036101ca5790565b67ffffffffffffffff60019116019067ffffffffffffffff821161142a57565b8054821015611cf85760005260206000200190600090565b3573ffffffffffffffffffffffffffffffffffffffff811681036101ca5790565b359067ffffffffffffffff821682036101ca57565b60065415611e3e577fffffffffffffffffffffffffffffffff0000000000000000000000000000000016600052600760205260406000205415801590611ded5790565b507f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b50600090565b60065415611e9c577f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b600090565b805115611cf85760200190565b8051821015611cf85760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff600154163303611ee357565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b600081815260076020526040902054801561209c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600654907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161142a5781810361202d575b5050506006548015611ffe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611fbb816006611d5c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600655600052600760205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61208461203e61204f936006611d5c565b90549060031b1c9283926006611d5c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526007602052604060002055388080611f82565b5050600090565b80600052600760205260406000205415600014611e3e5760065468010000000000000000811015610c19576120e461204f8260018594016006556006611d5c565b905560065490600052600760205260406000205560019056fea164736f6c634300081a000a0000000000000000000000000000000000000000000000002220395d5f2affe1000000000000000000000000b2084482e25fd637eb6d418d2ec91e5671cafdb1
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c8063181f5a77146119ce578063198f0f77146112df5780631add205f146111145780632cbc26bb146110d3578063397796f7146110905780634d61677114610f3557806362eed41514610e155780636509a95414610dbc5780636d2d399314610c9c57806370a9089e146105f057806379ba5097146105075780638da5cb5b146104b55780639a19b329146103c7578063d881e09214610322578063eaa83ddd146102bf578063f2fde38b146101cf5763f8bb876e146100d757600080fd5b346101ca576100e536611b71565b6100ed611ec2565b60005b81518110156101955761012e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b51166120a3565b1561013b576001016100f0565b610166907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f19d5c79b0000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b0390a1005b600080fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5773ffffffffffffffffffffffffffffffffffffffff61021b611b36565b610223611ec2565b1633811461029557807fffffffffffffffffffffffff0000000000000000000000000000000000000000600054161760005573ffffffffffffffffffffffffffffffffffffffff600154167fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278600080a3005b7fdad89dca0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602060405167ffffffffffffffff7f0000000000000000000000000000000000000000000000002220395d5f2affe1168152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760405180602060065491828152019060066000527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f9060005b8181106103b1576103ad856103a181870382611a67565b60405191829182611c38565b0390f35b825484526020909301926001928301920161038a565b346101ca576103d536611b71565b6103dd611ec2565b60005b81518110156104855761041e7fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b5116611f0d565b1561042b576001016103e0565b610456907fffffffffffffffffffffffffffffffff0000000000000000000000000000000092611eae565b51167f73281fa10000000000000000000000000000000000000000000000000000000060005260045260246000fd5b6040517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760005473ffffffffffffffffffffffffffffffffffffffff811633036105c6577fffffffffffffffffffffffff00000000000000000000000000000000000000006001549133828416176001551660005573ffffffffffffffffffffffffffffffffffffffff3391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b7f02b543c60000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610627611b36565b67ffffffffffffffff602435116101ca573660236024350112156101ca57602435600401359067ffffffffffffffff82116101ca573660248360051b81350101116101ca576044359067ffffffffffffffff82116101ca57366023830112156101ca5767ffffffffffffffff8260040135116101ca57366024836004013560061b840101116101ca5763ffffffff6005541615610c725767ffffffffffffffff6106d48160045416611d3c565b16826004013510610c485760025460405160c0810181811067ffffffffffffffff821117610c1957604052468152602081019267ffffffffffffffff7f0000000000000000000000000000000000000000000000002220395d5f2affe1168452604082019230845273ffffffffffffffffffffffffffffffffffffffff60608401921682526080830190815261076987611b59565b916107776040519384611a67565b8783526000976024803501602085015b60248360051b813501018210610a61575050509073ffffffffffffffffffffffffffffffffffffffff8095939260a0860193845260405196879567ffffffffffffffff602088019a7f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538c526040808a01526101208901995160608a015251166080880152511660a0860152511660c08401525160e08301525160c0610100830152805180935261014082019260206101408260051b85010192019388905b8282106109c8575050506108809250037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611a67565b5190208290815b83600401358310610896578480f35b60208560806108ad86886004013560248a01611ce8565b35836108c1888a6004013560248c01611ce8565b013560405191878352601b868401526040830152606082015282805260015afa156109bd5784519073ffffffffffffffffffffffffffffffffffffffff82169081156109955773ffffffffffffffffffffffffffffffffffffffff829116101561096d578552600860205260ff604086205416156109455760019290920191610887565b6004857faaaa9141000000000000000000000000000000000000000000000000000000008152fd5b6004867fbbe15e7f000000000000000000000000000000000000000000000000000000008152fd5b6004877f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d86823e3d90fd5b91936020847ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec08293600195970301855287519067ffffffffffffffff8251168152608080610a238585015160a08786015260a0850190611aa8565b9367ffffffffffffffff604082015116604085015267ffffffffffffffff606082015116606085015201519101529601920192018593919492610845565b81359067ffffffffffffffff8211610c155760a07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc836024350136030112610c15576040519060a0820182811067ffffffffffffffff821117610be457604052610ad060248481350101611d95565b82526044836024350101359167ffffffffffffffff8311610c115736604360243586018501011215610c115767ffffffffffffffff6024848682350101013511610be457908d9160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6024878982350101013501160193610b576040519586611a67565b60248035870182019081013580875236910160440111610be057602495602095869560a49387908a90813586018101808301359060440186850137858235010101358301015285840152610bb060648289350101611d95565b6040840152610bc460848289350101611d95565b6060840152863501013560808201528152019201919050610787565b8380fd5b60248e7f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b8d80fd5b8b80fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f59fa4a930000000000000000000000000000000000000000000000000000000060005260046000fd5b7face124bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610cd3611b07565b604090815190610ce38383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610d3a83611ea1565b91169052610d46611ec2565b60005b8151811015610d8d57610d807fffffffffffffffffffffffffffffffff000000000000000000000000000000006104178385611eae565b1561042b57600101610d49565b82517f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba190806101c58582611c38565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf538152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57610e4c611b07565b604090815190610e5c8383611a67565b600182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe083013660208401377fffffffffffffffffffffffffffffffff00000000000000000000000000000000610eb383611ea1565b91169052610ebf611ec2565b60005b8151811015610f0657610ef97fffffffffffffffffffffffffffffffff000000000000000000000000000000006101278385611eae565b1561013b57600101610ec2565b82517f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7490806101c58582611c38565b346101ca5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca57600073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b2084482e25fd637eb6d418d2ec91e5671cafdb1168015611068576020604491604051928380927f4d61677100000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff610fef611b36565b16600483015260243560248301525afa90811561105d57829161101a575b6020826040519015158152f35b90506020813d602011611055575b8161103560209383611a67565b810103126110515751801515810361105157602091508261100d565b5080fd5b3d9150611028565b6040513d84823e3d90fd5b6004827f0a7c4edd000000000000000000000000000000000000000000000000000000008152fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c9611e44565b6040519015158152f35b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760206110c961110f611b07565b611daa565b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760006040805161115281611a4b565b82815260606020820152015263ffffffff600554166040519061117482611a4b565b60025482526003549161118683611b59565b926111946040519485611a67565b808452600360009081527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9190602086015b82821061128057505050506020810192835267ffffffffffffffff6004541692604082019384526040519283526040602084015260a083019151604084015251906060808401528151809152602060c0840192019060005b81811061123e5750505067ffffffffffffffff8293511660808301520390f35b8251805173ffffffffffffffffffffffffffffffffffffffff16855260209081015167ffffffffffffffff16818601526040909401939092019160010161121e565b6040516040810181811067ffffffffffffffff821117610c1957600192839260209260405267ffffffffffffffff885473ffffffffffffffffffffffffffffffffffffffff8116835260a01c16838201528152019401910190926111c6565b346101ca5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca5760043567ffffffffffffffff81116101ca57806004018136039160607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8401126101ca5761135a611ec2565b81359081156119a457909260248201919060015b6113788486611c94565b90508110156114595761138b8486611c94565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83019183831161142a576113cc926020926113c692611ce8565b01611d27565b67ffffffffffffffff806113ef60206113c6866113e98b8d611c94565b90611ce8565b16911610156114005760010161136e565b7f448515170000000000000000000000000000000000000000000000000000000060005260046000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b508390856114678584611c94565b60448601915061147682611d27565b60011b6801fffffffffffffffe67fffffffffffffffe82169116810361142a576114a867ffffffffffffffff91611d3c565b161161197a57600354805b611877575060005b6114c58786611c94565b905081101561159e5773ffffffffffffffffffffffffffffffffffffffff6114f96114f4836113e98b8a611c94565b611d74565b16600052600860205260ff60406000205416611574578073ffffffffffffffffffffffffffffffffffffffff6115386114f46001946113e98c8b611c94565b1660005260086020526040600020827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055016114bb565b7f28cae27d0000000000000000000000000000000000000000000000000000000060005260046000fd5b50846115b08780959685600255611c94565b90680100000000000000008211610c195760035482600355808310611831575b50600360005260206000206000915b838310611783575050505067ffffffffffffffff6115fc83611d27565b167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000060045416176004556005549463ffffffff86169563ffffffff871461142a5763ffffffff60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000098011696879116176005557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd6040519560208752608087019560208801523591018112156101ca57016024600482013591019267ffffffffffffffff82116101ca578160061b360384136101ca578190606060408701525260a0840192906000905b80821061173057867f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c87808867ffffffffffffffff6117258a611d95565b1660608301520390a2005b90919384359073ffffffffffffffffffffffffffffffffffffffff82168092036101ca5760408160019382935267ffffffffffffffff61177260208a01611d95565b1660208201520195019201906116e7565b600160408273ffffffffffffffffffffffffffffffffffffffff6117a78495611d74565b167fffffffffffffffffffffffff00000000000000000000000000000000000000008654161785556117db60208201611d27565b7fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff7bffffffffffffffff000000000000000000000000000000000000000087549260a01b169116178555019201920191906115df565b60036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9081019083015b81811061186b57506115d0565b6000815560010161185e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600090600354111561194d57600390527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85a81015473ffffffffffffffffffffffffffffffffffffffff16600090815260086020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055801561142a577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01806114b3565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526032600452fd5b7f014c50200000000000000000000000000000000000000000000000000000000060005260046000fd5b7f9cf8540c0000000000000000000000000000000000000000000000000000000060005260046000fd5b346101ca5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101ca576103ad6040805190611a0f8183611a67565b600f82527f524d4e52656d6f746520312e362e300000000000000000000000000000000000602083015251918291602083526020830190611aa8565b6060810190811067ffffffffffffffff821117610c1957604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610c1957604052565b919082519283825260005b848110611af25750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006020809697860101520116010190565b80602080928401015182828601015201611ab3565b600435907fffffffffffffffffffffffffffffffff00000000000000000000000000000000821682036101ca57565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036101ca57565b67ffffffffffffffff8111610c195760051b60200190565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101ca576004359067ffffffffffffffff82116101ca57806023830112156101ca57816004013590611bc882611b59565b92611bd66040519485611a67565b8284526024602085019360051b8201019182116101ca57602401915b818310611bff5750505090565b82357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681036101ca57815260209283019201611bf2565b602060408183019282815284518094520192019060005b818110611c5c5750505090565b82517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016845260209384019390920191600101611c4f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101ca570180359067ffffffffffffffff82116101ca57602001918160061b360383136101ca57565b9190811015611cf85760061b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3567ffffffffffffffff811681036101ca5790565b67ffffffffffffffff60019116019067ffffffffffffffff821161142a57565b8054821015611cf85760005260206000200190600090565b3573ffffffffffffffffffffffffffffffffffffffff811681036101ca5790565b359067ffffffffffffffff821682036101ca57565b60065415611e3e577fffffffffffffffffffffffffffffffff0000000000000000000000000000000016600052600760205260406000205415801590611ded5790565b507f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b50600090565b60065415611e9c577f010000000000000000000000000000010000000000000000000000000000000060005260076020527f70b766b11586b6b505ed3893938b0cc6c6c98bd6f65e969ac311168d34e4f9e254151590565b600090565b805115611cf85760200190565b8051821015611cf85760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff600154163303611ee357565b7f2b5c74de0000000000000000000000000000000000000000000000000000000060005260046000fd5b600081815260076020526040902054801561209c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff810181811161142a57600654907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820191821161142a5781810361202d575b5050506006548015611ffe577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01611fbb816006611d5c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055600655600052600760205260006040812055600190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b61208461203e61204f936006611d5c565b90549060031b1c9283926006611d5c565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b90556000526007602052604060002055388080611f82565b5050600090565b80600052600760205260406000205415600014611e3e5760065468010000000000000000811015610c19576120e461204f8260018594016006556006611d5c565b905560065490600052600760205260406000205560019056fea164736f6c634300081a000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000002220395d5f2affe1000000000000000000000000b2084482e25fd637eb6d418d2ec91e5671cafdb1
-----Decoded View---------------
Arg [0] : localChainSelector (uint64): 2459028469735686113
Arg [1] : legacyRMN (address): 0xb2084482e25fd637eB6D418d2ec91E5671CAfDb1
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000002220395d5f2affe1
Arg [1] : 000000000000000000000000b2084482e25fd637eb6d418d2ec91e5671cafdb1
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.