Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
23680470 | 26 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x578CCAd6...FcE33328e The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Inbox
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.26; import {IMailbox, IPostDispatchHook} from "@hyperlane-xyz/core/contracts/interfaces/IMailbox.sol"; import {TypeCasts} from "@hyperlane-xyz/core/contracts/libs/TypeCasts.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./interfaces/IInbox.sol"; import "./interfaces/IMetalayerRouter.sol"; import {IInbox} from "./interfaces/IInbox.sol"; import {Intent, Route, Call, TokenAmount} from "./types/Intent.sol"; import {Semver} from "./libs/Semver.sol"; /** * @title Inbox * @notice Main entry point for fulfilling intents * @dev Validates intent hash authenticity and executes calldata. Enables provers * to claim rewards on the source chain by checking the fulfilled mapping */ contract Inbox is IInbox, Ownable, Semver { using TypeCasts for address; using SafeERC20 for IERC20; // Mapping of intent hash on the src chain to its fulfillment mapping(bytes32 => address) public fulfilled; // Mapping of solvers to if they are whitelisted mapping(address => bool) public solverWhitelist; // address of local hyperlane mailbox address public mailbox; // address of local metalayer router address public router; // Is solving public bool public isSolvingPublic; /** * @notice Initializes the Inbox contract * @dev Privileged functions are designed to only allow one-time changes * @param _owner Address with access to privileged functions * @param _isSolvingPublic Whether solving is public at start * @param _solvers Initial whitelist of solvers (only relevant if solving is not public) */ constructor( address _owner, bool _isSolvingPublic, address[] memory _solvers ) Ownable(_owner) { isSolvingPublic = _isSolvingPublic; for (uint256 i = 0; i < _solvers.length; ++i) { solverWhitelist[_solvers[i]] = true; emit SolverWhitelistChanged(_solvers[i], true); } } /** * @notice Fulfills an intent to be proven via storage proofs * @param _route The route of the intent * @param _rewardHash The hash of the reward * @param _claimant The address that will receive the reward on the source chain * @param _expectedHash The hash of the intent as created on the source chain * @return Array of execution results from each call */ function fulfillStorage( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash ) external payable returns (bytes[] memory) { bytes[] memory result = _fulfill( _route, _rewardHash, _claimant, _expectedHash ); emit ToBeProven(_expectedHash, _route.source, _claimant); return result; } /** * @notice Fulfills an intent to be proven immediately via Hyperlane's mailbox * @dev More expensive but faster than hyperbatched. Requires fee for Hyperlane infrastructure * @param _route The route of the intent * @param _rewardHash The hash of the reward * @param _claimant The address that will receive the reward on the source chain * @param _expectedHash The hash of the intent as created on the source chain * @param _prover The address of the hyperprover on the source chain * @return Array of execution results from each call */ function fulfillHyperInstant( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash, address _prover ) external payable returns (bytes[] memory) { return fulfillHyperInstantWithRelayer( _route, _rewardHash, _claimant, _expectedHash, _prover, bytes(""), address(0) ); } /** * @notice Fulfills an intent to be proven immediately via Hyperlane's mailbox with relayer support * @dev More expensive but faster than hyperbatched. Requires fee for Hyperlane infrastructure * @param _route The route of the intent * @param _rewardHash The hash of the reward * @param _claimant The address that will receive the reward on the source chain * @param _expectedHash The hash of the intent as created on the source chain * @param _prover The address of the hyperprover on the source chain * @param _metadata Metadata for postDispatchHook (empty bytes if not applicable) * @param _postDispatchHook Address of postDispatchHook (zero address if not applicable) * @return Array of execution results from each call */ function fulfillHyperInstantWithRelayer( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash, address _prover, bytes memory _metadata, address _postDispatchHook ) public payable returns (bytes[] memory) { bytes32[] memory hashes = new bytes32[](1); address[] memory claimants = new address[](1); hashes[0] = _expectedHash; claimants[0] = _claimant; bytes memory messageBody = abi.encode(hashes, claimants); bytes32 _prover32 = _prover.addressToBytes32(); emit HyperInstantFulfillment(_expectedHash, _route.source, _claimant); uint256 fee = fetchFee( _route.source, _prover32, messageBody, _metadata, _postDispatchHook ); bytes[] memory results = _fulfill( _route, _rewardHash, _claimant, _expectedHash ); uint256 currentBalance = address(this).balance; if (currentBalance < fee) { revert InsufficientFee(fee); } if (currentBalance > fee) { (bool success, ) = payable(msg.sender).call{ value: currentBalance - fee }(""); if (!success) { revert NativeTransferFailed(); } } if (_postDispatchHook == address(0)) { IMailbox(mailbox).dispatch{value: fee}( uint32(_route.source), _prover32, messageBody ); } else { IMailbox(mailbox).dispatch{value: fee}( uint32(_route.source), _prover32, messageBody, _metadata, IPostDispatchHook(_postDispatchHook) ); } return results; } /** * @notice Fulfills an intent to be proven in a batch via Hyperlane's mailbox * @dev Less expensive but slower than hyperinstant. Batch dispatched when sendBatch is called. * @param _route The route of the intent * @param _rewardHash The hash of the reward * @param _claimant The address that will receive the reward on the source chain * @param _expectedHash The hash of the intent as created on the source chain * @param _prover The address of the hyperprover on the source chain * @return Array of execution results from each call */ function fulfillHyperBatched( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash, address _prover ) external payable returns (bytes[] memory) { emit AddToBatch(_expectedHash, _route.source, _claimant, _prover); bytes[] memory results = _fulfill( _route, _rewardHash, _claimant, _expectedHash ); return results; } /** * @notice Sends a batch of fulfilled intents to the mailbox * @dev Intent hashes must correspond to fulfilled intents from specified source chain * @param _sourceChainID Chain ID of the source chain * @param _prover Address of the hyperprover on the source chain * @param _intentHashes Hashes of the intents to be proven */ function sendBatch( uint256 _sourceChainID, address _prover, bytes32[] calldata _intentHashes ) external payable { sendBatchWithRelayer( _sourceChainID, _prover, _intentHashes, bytes(""), address(0) ); } /** * @notice Sends a batch of fulfilled intents to the mailbox with relayer support * @dev Intent hashes must correspond to fulfilled intents from specified source chain * @param _sourceChainID Chain ID of the source chain * @param _prover Address of the hyperprover on the source chain * @param _intentHashes Hashes of the intents to be proven * @param _metadata Metadata for postDispatchHook * @param _postDispatchHook Address of postDispatchHook */ function sendBatchWithRelayer( uint256 _sourceChainID, address _prover, bytes32[] calldata _intentHashes, bytes memory _metadata, address _postDispatchHook ) public payable { uint256 size = _intentHashes.length; address[] memory claimants = new address[](size); for (uint256 i = 0; i < size; ++i) { address claimant = fulfilled[_intentHashes[i]]; if (claimant == address(0)) { revert IntentNotFulfilled(_intentHashes[i]); } claimants[i] = claimant; } emit BatchSent(_intentHashes, _sourceChainID); bytes memory messageBody = abi.encode(_intentHashes, claimants); bytes32 _prover32 = _prover.addressToBytes32(); uint256 fee = fetchFee( _sourceChainID, _prover32, messageBody, _metadata, _postDispatchHook ); if (msg.value < fee) { revert InsufficientFee(fee); } if (msg.value > fee) { (bool success, ) = payable(msg.sender).call{value: msg.value - fee}( "" ); if (!success) { revert NativeTransferFailed(); } } if (_postDispatchHook == address(0)) { IMailbox(mailbox).dispatch{value: fee}( uint32(_sourceChainID), _prover32, messageBody ); } else { IMailbox(mailbox).dispatch{value: fee}( uint32(_sourceChainID), _prover32, messageBody, _metadata, IPostDispatchHook(_postDispatchHook) ); } } /** * @notice Quotes the fee required for message dispatch * @dev Used to determine fees for fulfillHyperInstant or sendBatch * @param _sourceChainID Chain ID of the source chain * @param _prover Address of the hyperprover on the source chain * @param _messageBody Message being sent over the bridge * @param _metadata Metadata for postDispatchHook * @param _postDispatchHook Address of postDispatchHook * @return fee The required fee amount */ function fetchFee( uint256 _sourceChainID, bytes32 _prover, bytes memory _messageBody, bytes memory _metadata, address _postDispatchHook ) public view returns (uint256 fee) { return ( _postDispatchHook == address(0) ? IMailbox(mailbox).quoteDispatch( uint32(_sourceChainID), _prover, _messageBody ) : IMailbox(mailbox).quoteDispatch( uint32(_sourceChainID), _prover, _messageBody, _metadata, IPostDispatchHook(_postDispatchHook) ) ); } /** * @notice Sets the mailbox address * @dev Can only be called once during deployment * @param _mailbox Address of the Hyperlane mailbox */ function setMailbox(address _mailbox) public onlyOwner { if (mailbox == address(0)) { mailbox = _mailbox; emit MailboxSet(_mailbox); } } /** * @notice allows the owner to set the metalayer router * @param _router the address of the router * @dev this can only be called once, to initialize the router, and should be called at time of deployment */ function setRouter(address _router) public onlyOwner { if (router == address(0)) { router = _router; emit RouterSet(_router); } } /** * @notice Makes solving public if currently restricted * @dev Cannot be reversed once made public */ function makeSolvingPublic() public onlyOwner { if (!isSolvingPublic) { isSolvingPublic = true; emit SolvingIsPublic(); } } /** * @notice Updates the solver whitelist * @dev Whitelist is ignored if solving is public * @param _solver Address of the solver * @param _canSolve Whether solver should be whitelisted */ function changeSolverWhitelist( address _solver, bool _canSolve ) public onlyOwner { solverWhitelist[_solver] = _canSolve; emit SolverWhitelistChanged(_solver, _canSolve); } /** * @notice Internal function to fulfill intents * @dev Validates intent and executes calls * @param _route The route of the intent * @param _rewardHash The hash of the reward * @param _claimant The reward recipient address * @param _expectedHash The expected intent hash * @return Array of execution results */ function _fulfill( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash ) internal returns (bytes[] memory) { if (!isSolvingPublic && !solverWhitelist[msg.sender]) { revert UnauthorizedSolveAttempt(msg.sender); } bytes32 routeHash = keccak256(abi.encode(_route)); bytes32 intentHash = keccak256( abi.encodePacked(routeHash, _rewardHash) ); if (_route.inbox != address(this)) { revert InvalidInbox(_route.inbox); } if (intentHash != _expectedHash) { revert InvalidHash(_expectedHash); } if (fulfilled[intentHash] != address(0)) { revert IntentAlreadyFulfilled(intentHash); } if (_claimant == address(0)) { revert ZeroClaimant(); } fulfilled[intentHash] = _claimant; emit Fulfillment(_expectedHash, _route.source, _claimant); uint256 routeTokenCount = _route.tokens.length; // Transfer ERC20 tokens to the inbox for (uint256 i = 0; i < routeTokenCount; ++i) { TokenAmount memory approval = _route.tokens[i]; IERC20(approval.token).safeTransferFrom( msg.sender, address(this), approval.amount ); } // Store the results of the calls bytes[] memory results = new bytes[](_route.calls.length); for (uint256 i = 0; i < _route.calls.length; ++i) { Call calldata call = _route.calls[i]; if (call.target == mailbox) { // no executing calls on the mailbox revert CallToMailbox(); } (bool success, bytes memory result) = call.target.call{ value: call.value }(call.data); if (!success) { revert IntentCallFailed( call.target, call.data, call.value, result ); } results[i] = result; } return results; } /** * This function generates the intent hash * @param _sourceChainID the chainID of the source chain * @param _chainId the chainId of this chain * @param _inboxAddress the address of this contract * @param _targets The addresses to call * @param _data The calldata to call * @param _expiryTime The timestamp at which the intent expires * @param _nonce The nonce of the calldata. Composed of the hash on the src chain of a global nonce & chainID * @return hash The hash of the intent parameters */ function encodeHash( uint256 _sourceChainID, uint256 _chainId, address _inboxAddress, address[] calldata _targets, bytes[] calldata _data, uint256 _expiryTime, bytes32 _nonce ) internal pure returns (bytes32) { return keccak256( abi.encode( _inboxAddress, keccak256( abi.encode( _sourceChainID, _chainId, _targets, _data, _expiryTime, _nonce ) ) ) ); } /** * @notice Fulfills an intent to be proven immediately via Metalayer's router. * @param _expectedHash The hash of the intent as created on the source chain * @param _prover The address of the metalayer prover on the source chain * @return the fulfilled results */ function fulfillMetalayerInstant( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash, address _prover ) external payable returns (bytes[] memory) { bytes32[] memory hashes = new bytes32[](1); address[] memory claimants = new address[](1); hashes[0] = _expectedHash; claimants[0] = _claimant; bytes memory messageBody = abi.encode(hashes, claimants); emit MetalayerInstantFulfillment(_expectedHash, _route.source, _claimant); bytes[] memory results = _fulfill( _route, _rewardHash, _claimant, _expectedHash ); IMetalayerRouter(router).dispatch{value: msg.value}( uint32(_route.source), _prover, new ReadOperation[](0), messageBody ); // TODO: Enable fee support for Metalayer instant fulfillment // uint256 expectedFee = fetchMetalayerFee(...); // if (msg.value > expectedFee) { // (bool success, ) = payable(msg.sender).call{value: msg.value - expectedFee}(""); // require(success, "Native transfer failed."); // } return results; } receive() external payable {} }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ interface IPostDispatchHook { enum Types { UNUSED, ROUTING, AGGREGATION, MERKLE_TREE, INTERCHAIN_GAS_PAYMASTER, FALLBACK_ROUTING, ID_AUTH_ISM, PAUSABLE, PROTOCOL_FEE, LAYER_ZERO_V1, RATE_LIMITED, ARB_L2_TO_L1, OP_L2_TO_L1 } /** * @notice Returns an enum that represents the type of hook */ function hookType() external view returns (uint8); /** * @notice Returns whether the hook supports metadata * @param metadata metadata * @return Whether the hook supports metadata */ function supportsMetadata( bytes calldata metadata ) external view returns (bool); /** * @notice Post action after a message is dispatched via the Mailbox * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call */ function postDispatch( bytes calldata metadata, bytes calldata message ) external payable; /** * @notice Compute the payment required by the postDispatch call * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call * @return Quoted payment for the postDispatch call */ function quoteDispatch( bytes calldata metadata, bytes calldata message ) external view returns (uint256); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; interface IInterchainSecurityModule { enum Types { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ, ARB_L2_TO_L1, WEIGHT_MERKLE_ROOT_MULTISIG, WEIGHT_MESSAGE_ID_MULTISIG, OP_L2_TO_L1 } /** * @notice Returns an enum that represents the type of security model * encoded by this ISM. * @dev Relayers infer how to fetch and format metadata. */ function moduleType() external view returns (uint8); /** * @notice Defines a security model responsible for verifying interchain * messages based on the provided metadata. * @param _metadata Off-chain metadata provided by a relayer, specific to * the security model encoded by the module (e.g. validator signatures) * @param _message Hyperlane encoded interchain message * @return True if the message was verified */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool); } interface ISpecifiesInterchainSecurityModule { function interchainSecurityModule() external view returns (IInterchainSecurityModule); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol"; import {IPostDispatchHook} from "./hooks/IPostDispatchHook.sol"; interface IMailbox { // ============ Events ============ /** * @notice Emitted when a new message is dispatched via Hyperlane * @param sender The address that dispatched the message * @param destination The destination domain of the message * @param recipient The message recipient address on `destination` * @param message Raw bytes of message */ event Dispatch( address indexed sender, uint32 indexed destination, bytes32 indexed recipient, bytes message ); /** * @notice Emitted when a new message is dispatched via Hyperlane * @param messageId The unique message identifier */ event DispatchId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is processed * @param messageId The unique message identifier */ event ProcessId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is delivered * @param origin The origin domain of the message * @param sender The message sender address on `origin` * @param recipient The address that handled the message */ event Process( uint32 indexed origin, bytes32 indexed sender, address indexed recipient ); function localDomain() external view returns (uint32); function delivered(bytes32 messageId) external view returns (bool); function defaultIsm() external view returns (IInterchainSecurityModule); function defaultHook() external view returns (IPostDispatchHook); function requiredHook() external view returns (IPostDispatchHook); function latestDispatchedId() external view returns (bytes32); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata defaultHookMetadata ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata defaultHookMetadata ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external view returns (uint256 fee); function process( bytes calldata metadata, bytes calldata message ) external payable; function recipientIsm( address recipient ) external view returns (IInterchainSecurityModule module); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; library TypeCasts { // alignment preserving cast function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } // alignment preserving cast function bytes32ToAddress(bytes32 _buf) internal pure returns (address) { return address(uint160(uint256(_buf))); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.26; import {ISemver} from "./ISemver.sol"; import {ReadOperation} from "./IMetalayerRecipient.sol"; import {Route} from "../types/Intent.sol"; /** * @title IInbox * @notice Interface for the destination chain portion of the Eco Protocol's intent system * @dev Handles intent fulfillment and proving via different mechanisms (storage proofs, * Hyperlane instant/batched) */ interface IInbox is ISemver { /** * @notice Emitted when an intent is successfully fulfilled * @param _hash Hash of the fulfilled intent * @param _sourceChainID ID of the source chain * @param _claimant Address eligible to claim rewards */ event Fulfillment( bytes32 indexed _hash, uint256 indexed _sourceChainID, address indexed _claimant ); /** * @notice Emitted when an intent is ready for storage proof validation * @param _hash Hash of the intent to prove * @param _sourceChainID ID of the source chain * @param _claimant Address eligible to claim rewards */ event ToBeProven( bytes32 indexed _hash, uint256 indexed _sourceChainID, address indexed _claimant ); /** * @notice Emitted when an intent is fulfilled using Hyperlane instant proving * @param _hash Hash of the fulfilled intent * @param _sourceChainID ID of the source chain * @param _claimant Address eligible to claim rewards */ event HyperInstantFulfillment( bytes32 indexed _hash, uint256 indexed _sourceChainID, address indexed _claimant ); /** * @notice Emitted when an intent is added to a Hyperlane batch * @param _hash Hash of the batched intent * @param _sourceChainID ID of the source chain * @param _claimant Address eligible to claim rewards * @param _prover Address of the Hyperlane prover */ event AddToBatch( bytes32 indexed _hash, uint256 indexed _sourceChainID, address indexed _claimant, address _prover ); /** * @notice Emitted when intent solving is made public * @param _hashes the intent hashes sent in the batch * @param _sourceChainID ID of the source chain */ event BatchSent(bytes32[] indexed _hashes, uint256 indexed _sourceChainID); /** * @notice Emitted when intent solving is made public */ event SolvingIsPublic(); /** * @notice Emitted when Hyperlane mailbox address is set * @param _mailbox Address of the mailbox contract */ event MailboxSet(address indexed _mailbox); /** * @notice Emitted when solver whitelist status changes * @param _solver Address of the solver * @param _canSolve Updated whitelist status */ event SolverWhitelistChanged( address indexed _solver, bool indexed _canSolve ); /** * @notice Emitted when an intent is fulfilled using Metalayer instant proving * @param _hash Hash of the fulfilled intent * @param _sourceChainID ID of the source chain * @param _claimant Address eligible to claim rewards */ event MetalayerInstantFulfillment( bytes32 indexed _hash, uint256 indexed _sourceChainID, address indexed _claimant ); /** * @notice Emitted when Metalayer Router is set * @param _router Address of the router contract */ event RouterSet(address indexed _router); /** * @notice Unauthorized solver attempted to fulfill intent * @param _solver Address of the unauthorized solver */ error UnauthorizedSolveAttempt(address _solver); /** * @notice Intent has expired and can no longer be fulfilled */ error IntentExpired(); /** * @notice Intent has already been fulfilled * @param _hash Hash of the fulfilled intent */ error IntentAlreadyFulfilled(bytes32 _hash); /** * @notice Invalid inbox address provided * @param _inbox Address that is not a valid inbox */ error InvalidInbox(address _inbox); /** * @notice Generated hash doesn't match expected hash * @param _expectedHash Hash that was expected */ error InvalidHash(bytes32 _expectedHash); /** * @notice Zero address provided as claimant */ error ZeroClaimant(); /** * @notice Call during intent execution failed * @param _addr Target contract address * @param _data Call data that failed * @param value Native token value sent * @param _returnData Error data returned */ error IntentCallFailed( address _addr, bytes _data, uint256 value, bytes _returnData ); /** * @notice Attempted call to Hyperlane mailbox */ error CallToMailbox(); /** * @notice Unauthorized attempt to transfer native tokens */ error UnauthorizedTransferNative(); /** * @notice Attempted to batch an unfulfilled intent * @param _hash Hash of the unfulfilled intent */ error IntentNotFulfilled(bytes32 _hash); /** * @notice Insufficient fee provided for Hyperlane fulfillment * @param _requiredFee Amount of fee required */ error InsufficientFee(uint256 _requiredFee); /** * @notice Native token transfer failed */ error NativeTransferFailed(); /** * @notice Fulfills an intent using storage proofs * @dev Validates intent hash, executes calls, and marks as fulfilled * @param _route Route information for the intent * @param _rewardHash Hash of the reward details * @param _claimant Address eligible to claim rewards * @param _expectedHash Expected hash for validation * @return Array of execution results */ function fulfillStorage( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash ) external payable returns (bytes[] memory); /** * @notice Fulfills an intent with immediate Hyperlane proving * @dev Higher cost but faster than batched proving * @param _route Route information for the intent * @param _rewardHash Hash of the reward details * @param _claimant Address eligible to claim rewards * @param _expectedHash Expected hash for validation * @param _prover Address of the Hyperlane prover * @return Array of execution results */ function fulfillHyperInstant( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash, address _prover ) external payable returns (bytes[] memory); /** * @notice Fulfills an intent for deferred Hyperlane batch proving * @dev Lower cost but slower than instant proving * @param _route Route information for the intent * @param _rewardHash Hash of the reward details * @param _claimant Address eligible to claim rewards * @param _expectedHash Expected hash for validation * @param _prover Address of the Hyperlane prover * @return Array of execution results */ function fulfillHyperBatched( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash, address _prover ) external payable returns (bytes[] memory); /** * @notice Submits a batch of fulfilled intents to Hyperlane * @dev All intents must share source chain and prover * @param _sourceChainID Source chain ID for the batch * @param _prover Hyperlane prover address * @param _intentHashes Array of intent hashes to prove */ function sendBatch( uint256 _sourceChainID, address _prover, bytes32[] calldata _intentHashes ) external payable; /** * Same as above but with the added _prover parameter. This fulfill method is used to fulfill an intent that is proving with the MetalayerProver and wishes to prove immediately. * @param _expectedHash The hash a solver should expect to be generated from the params above. * @dev this is a guardrail to make sure solves dont accidentally solve intents that cannot be proven. * @param _prover The prover against which this intent will be checked */ function fulfillMetalayerInstant( Route calldata _route, bytes32 _rewardHash, address _claimant, bytes32 _expectedHash, address _prover ) external payable returns (bytes[] memory); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; /** * @notice Struct defining a cross-chain read operation * @param sourceChainId Domain of the chain to read from * @param sourceContract Contract address to read from as address * @param callDataLength Length of the call data * @param callData The encoded function call data */ struct ReadOperation { uint32 sourceChainId; address sourceContract; bytes callData; } interface IMetalayerRecipient { // Here, _readResults will be the results of every read in the message, in order. This will be input by the relayer. function handle( uint32 _chainId, address _sender, bytes calldata _message, // The body of the Metalayer message, or writeCallData. ReadOperation[] calldata _reads, bytes[] calldata _readResults ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.26; import {ReadOperation} from "./IMetalayerRecipient.sol"; interface IMetalayerRouter { /** * @notice Dispatches a message to the destination domain & recipient with the given reads and write. * @param _destinationDomain Domain of destination chain * @param _recipientAddress Address of recipient on destination chain * @param _reads Read operations * @param _writeCallData The raw bytes to be called on the recipient address. */ function dispatch( uint32 _destinationDomain, address _recipientAddress, ReadOperation[] memory _reads, bytes memory _writeCallData ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.26; /** * @title Semver Interface * @dev An interface for a contract that has a version */ interface ISemver { function version() external pure returns (string memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.26; import {ISemver} from "../interfaces/ISemver.sol"; abstract contract Semver is ISemver { function version() external pure returns (string memory) { return "1.8.14-e2c12e7"; } }
/* -*- c-basic-offset: 4 -*- */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.26; /** * @notice Represents a single contract call with encoded function data * @dev Used to execute arbitrary function calls on the destination chain * @param target The contract address to call * @param data ABI-encoded function call data * @param value Amount of native tokens to send with the call */ struct Call { address target; bytes data; uint256 value; } /** * @notice Represents a token amount pair * @dev Used to specify token rewards and transfers * @param token Address of the ERC20 token contract * @param amount Amount of tokens in the token's smallest unit */ struct TokenAmount { address token; uint256 amount; } /** * @notice Defines the routing and execution instructions for cross-chain messages * @dev Contains all necessary information to route and execute a message on the destination chain * @param salt Unique identifier provided by the intent creator, used to prevent duplicates * @param source Chain ID where the intent originated * @param destination Target chain ID where the calls should be executed * @param inbox Address of the inbox contract on the destination chain that receives messages * @param tokens Array of tokens required for execution of calls on destination chain * @param calls Array of contract calls to execute on the destination chain in sequence */ struct Route { bytes32 salt; uint256 source; uint256 destination; address inbox; TokenAmount[] tokens; Call[] calls; } /** * @notice Defines the reward and validation parameters for cross-chain execution * @dev Specifies who can execute the intent and what rewards they receive * @param creator Address that created the intent and has authority to modify/cancel * @param prover Address of the prover contract that must approve execution * @param deadline Timestamp after which the intent can no longer be executed * @param nativeValue Amount of native tokens offered as reward * @param tokens Array of ERC20 tokens and amounts offered as additional rewards */ struct Reward { address creator; address prover; uint256 deadline; uint256 nativeValue; TokenAmount[] tokens; } /** * @notice Complete cross-chain intent combining routing and reward information * @dev Main structure used to process and execute cross-chain messages * @param route Routing and execution instructions * @param reward Reward and validation parameters */ struct Intent { Route route; Reward reward; }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bool","name":"_isSolvingPublic","type":"bool"},{"internalType":"address[]","name":"_solvers","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"CallToMailbox","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requiredFee","type":"uint256"}],"name":"InsufficientFee","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"IntentAlreadyFulfilled","type":"error"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"_returnData","type":"bytes"}],"name":"IntentCallFailed","type":"error"},{"inputs":[],"name":"IntentExpired","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"}],"name":"IntentNotFulfilled","type":"error"},{"inputs":[{"internalType":"bytes32","name":"_expectedHash","type":"bytes32"}],"name":"InvalidHash","type":"error"},{"inputs":[{"internalType":"address","name":"_inbox","type":"address"}],"name":"InvalidInbox","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"address","name":"_solver","type":"address"}],"name":"UnauthorizedSolveAttempt","type":"error"},{"inputs":[],"name":"UnauthorizedTransferNative","type":"error"},{"inputs":[],"name":"ZeroClaimant","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_hash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_claimant","type":"address"},{"indexed":false,"internalType":"address","name":"_prover","type":"address"}],"name":"AddToBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32[]","name":"_hashes","type":"bytes32[]"},{"indexed":true,"internalType":"uint256","name":"_sourceChainID","type":"uint256"}],"name":"BatchSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_hash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_claimant","type":"address"}],"name":"Fulfillment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_hash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_claimant","type":"address"}],"name":"HyperInstantFulfillment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_mailbox","type":"address"}],"name":"MailboxSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_hash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_claimant","type":"address"}],"name":"MetalayerInstantFulfillment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_router","type":"address"}],"name":"RouterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_solver","type":"address"},{"indexed":true,"internalType":"bool","name":"_canSolve","type":"bool"}],"name":"SolverWhitelistChanged","type":"event"},{"anonymous":false,"inputs":[],"name":"SolvingIsPublic","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_hash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"indexed":true,"internalType":"address","name":"_claimant","type":"address"}],"name":"ToBeProven","type":"event"},{"inputs":[{"internalType":"address","name":"_solver","type":"address"},{"internalType":"bool","name":"_canSolve","type":"bool"}],"name":"changeSolverWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"internalType":"bytes32","name":"_prover","type":"bytes32"},{"internalType":"bytes","name":"_messageBody","type":"bytes"},{"internalType":"bytes","name":"_metadata","type":"bytes"},{"internalType":"address","name":"_postDispatchHook","type":"address"}],"name":"fetchFee","outputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"source","type":"uint256"},{"internalType":"uint256","name":"destination","type":"uint256"},{"internalType":"address","name":"inbox","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenAmount[]","name":"tokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"}],"internalType":"struct Route","name":"_route","type":"tuple"},{"internalType":"bytes32","name":"_rewardHash","type":"bytes32"},{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"bytes32","name":"_expectedHash","type":"bytes32"},{"internalType":"address","name":"_prover","type":"address"}],"name":"fulfillHyperBatched","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"source","type":"uint256"},{"internalType":"uint256","name":"destination","type":"uint256"},{"internalType":"address","name":"inbox","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenAmount[]","name":"tokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"}],"internalType":"struct Route","name":"_route","type":"tuple"},{"internalType":"bytes32","name":"_rewardHash","type":"bytes32"},{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"bytes32","name":"_expectedHash","type":"bytes32"},{"internalType":"address","name":"_prover","type":"address"}],"name":"fulfillHyperInstant","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"source","type":"uint256"},{"internalType":"uint256","name":"destination","type":"uint256"},{"internalType":"address","name":"inbox","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenAmount[]","name":"tokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"}],"internalType":"struct Route","name":"_route","type":"tuple"},{"internalType":"bytes32","name":"_rewardHash","type":"bytes32"},{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"bytes32","name":"_expectedHash","type":"bytes32"},{"internalType":"address","name":"_prover","type":"address"},{"internalType":"bytes","name":"_metadata","type":"bytes"},{"internalType":"address","name":"_postDispatchHook","type":"address"}],"name":"fulfillHyperInstantWithRelayer","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"source","type":"uint256"},{"internalType":"uint256","name":"destination","type":"uint256"},{"internalType":"address","name":"inbox","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenAmount[]","name":"tokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"}],"internalType":"struct Route","name":"_route","type":"tuple"},{"internalType":"bytes32","name":"_rewardHash","type":"bytes32"},{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"bytes32","name":"_expectedHash","type":"bytes32"},{"internalType":"address","name":"_prover","type":"address"}],"name":"fulfillMetalayerInstant","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"source","type":"uint256"},{"internalType":"uint256","name":"destination","type":"uint256"},{"internalType":"address","name":"inbox","type":"address"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct TokenAmount[]","name":"tokens","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"internalType":"struct Call[]","name":"calls","type":"tuple[]"}],"internalType":"struct Route","name":"_route","type":"tuple"},{"internalType":"bytes32","name":"_rewardHash","type":"bytes32"},{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"bytes32","name":"_expectedHash","type":"bytes32"}],"name":"fulfillStorage","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"fulfilled","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSolvingPublic","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mailbox","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"makeSolvingPublic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"internalType":"address","name":"_prover","type":"address"},{"internalType":"bytes32[]","name":"_intentHashes","type":"bytes32[]"}],"name":"sendBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sourceChainID","type":"uint256"},{"internalType":"address","name":"_prover","type":"address"},{"internalType":"bytes32[]","name":"_intentHashes","type":"bytes32[]"},{"internalType":"bytes","name":"_metadata","type":"bytes"},{"internalType":"address","name":"_postDispatchHook","type":"address"}],"name":"sendBatchWithRelayer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_mailbox","type":"address"}],"name":"setMailbox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_router","type":"address"}],"name":"setRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"solverWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c806327048b0f1461100a5780632aa91bfd14610fd75780632c16840214610f6457806340f3a5a814610f3e5780634667d3e514610d365780634a0e9d3a14610cd057806350b8452614610c6d57806354fd4d5014610c1b57806362b3a77c14610bdc578063715018a614610b825780637e0bdf8c14610af75780638da5cb5b14610ad0578063a0de4bbb14610866578063b15e2e9c146105ab578063c0d786551461052d578063caae303c146104b4578063d5438eae1461048b578063e1312bb71461023d578063f2fde38b146101b7578063f3c61d6b146101395763f887ea401461010e575061000e565b346101365780600319360112610136576004546040516001600160a01b039091168152602090f35b80fd5b5034610136576020366003190112610136576101536111ef565b61015b611e15565b600354906001600160a01b03821615610172578280f35b6001600160a01b03166001600160a01b03199190911681176003557f7a61e573722ff8b205c8962b59d37e7d30573f368965597a844a94872204ebd78280a238808280f35b5034610136576020366003190112610136576101d16111ef565b6101d9611e15565b6001600160a01b031680156102295781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b506060366003190112610136576004359061025661121b565b6044356001600160401b038111610487576102759036906004016113e2565b9390602092604051906102888583611349565b858252610294876115da565b96865b81811061042e57506040519697959694958895946001600160fb1b03831161042a5787958360051b9181838281943780838101039020946040519a8b967fd6383b4658ff90fe5c7fb8d1fe7a0b6cc87b7ecaf49d2305c1fed682f39548328c80a36040868d0152606086015260808501378201601f1983820360800101604084015260800161032591611643565b03601f19810186526103379086611349565b6001600160a01b03169261034d91858585611492565b80341061041857908185939234116103dd575b63ffffffff9060018060a01b0360035416926103936040519788968795869463fa31de0160e01b8652166004850161146d565b03925af180156103d2576103a5578280f35b816103c492903d106103cb575b6103bc8183611349565b810190611412565b5038808280f35b503d6103b2565b6040513d85823e3d90fd5b90919250858080806103ef85346116e0565b335af16103fa611703565b50156104095790849291610360565b633d2cec6f60e21b8652600486fd5b63131398d760e21b8652600452602485fd5b8680fd5b6104398183876116d0565b3588526001875260408820546001600160a01b031680156104695790600191610462828c61162f565b5201610297565b60248961047784868a6116d0565b636d5ba68f60e11b825235600452fd5b8280fd5b50346101365780600319360112610136576003546040516001600160a01b039091168152602090f35b5034610136576040366003190112610136576104ce6111ef565b60243590811515809203610487576104e4611e15565b6001600160a01b0316808352600260205260408320805460ff191660ff84161790557f3f3a0c23a11da402767747df1ed29891ffc0a54d42f3e8c767548cd45b7dd6788380a380f35b5034610136576020366003190112610136576105476111ef565b61054f611e15565b600454906001600160a01b03821615610566578280f35b6001600160a01b03166001600160a01b03199190911681176004557fc6b438e6a8a59579ce6a4406cbd203b740e0d47b458aae6596339bcd40c40d158280a238808280f35b5060e0366003190112610136576004356001600160401b0381116108625760c06003198236030112610862576105df611205565b906064356105eb6111d4565b60a4356001600160401b03811161085e5761060a90369060040161139b565b60c4356001600160a01b0381169590939086850361085a57604095828751966106338989611349565b60018852601f19890196873660208b01378951976106518b8a611349565b600189523660208a0137826106658a61160c565b5261066f8861160c565b6001600160a01b038616908190528a519990988a91610692919060208401611680565b03601f1981018a526106a4908a611349565b6001600160a01b03169660248401359586907f15299a9532f9e616b46fb1fff3ff56426e75c2cab158a32a4cae83547bfa3f748e80a46106e79086898988611492565b926106f89260243590600401611804565b96478281106108465780838b9211610812575b50509081602095949392156000146107a25750600354875163fa31de0160e01b81529687956001600160a01b03909216945085938492610755929163ffffffff166004850161146d565b03925af18015610798576107759450610779575b505b51918291826112e9565b0390f35b6107919060203d6020116103cb576103bc8183611349565b5038610769565b82513d86823e3d90fd5b60035488516242e0f760e61b81529788966001600160a01b0390921695879586946107d99490939163ffffffff1660048701611421565b03925af180156107985761077594506107f3575b5061076b565b61080b9060203d6020116103cb576103bc8183611349565b50386107ed565b818061081f8682946116e0565b335af161082a611703565b501561083757883861070b565b633d2cec6f60e21b8952600489fd5b63131398d760e21b8a52600483905260248afd5b8780fd5b8580fd5b5080fd5b5060a03660031901126101365760043561087e61121b565b916044356001600160401b0381116108625761089e9036906004016113e2565b9290936064356001600160401b038111610acc576108c090369060040161139b565b906108c96111d4565b946108d3816115da565b96855b828110610a825750604051916001600160fb1b03811161042a57869798608087610970957fd6383b4658ff90fe5c7fb8d1fe7a0b6cc87b7ecaf49d2305c1fed682f39548329a95856109629660051b93838584819637808581010390206040519e8f9a80a36040602089015260608801528387013784018481038201601f190160408601520190611643565b03601f198101865285611349565b6001600160a01b0316916109878683868685611492565b80341061041857803411610a55575b949593946020946001600160a01b031680610a1d575060035460405163fa31de0160e01b81529687956001600160a01b039092169450859384926109e4929163ffffffff166004850161146d565b03925af18015610a12576109f6575080f35b610a0e9060203d6020116103cb576103bc8183611349565b5080f35b6040513d84823e3d90fd5b6003546040516242e0f760e61b81529788966001600160a01b0390921695879586946109e49490939163ffffffff1660048701611421565b85808080610a6385346116e0565b335af1610a6e611703565b5061099657633d2cec6f60e21b8652600486fd5b610a8d8184846116d0565b358752600160205260408720546001600160a01b03168015610abe5790600191610ab7828c61162f565b52016108d6565b6024886104778487876116d0565b8380fd5b5034610136578060031936011261013657546040516001600160a01b039091168152602090f35b506080366003190112610136576004356001600160401b0381116108625760c0600319823603011261086257610775602492610b31611205565b9260643591610b468386883585600401611804565b927f160fbf39d03c171cfc82812374f495fff22339e6f2482ce8366139b1710d003b60405197889760018060a01b03169401359280a4826112e9565b5034610136578060031936011261013657610b9b611e15565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101365760203660031901126101365760209060ff906040906001600160a01b03610c076111ef565b168152600284522054166040519015158152f35b503461013657806003193601126101365750610775604051610c3e604082611349565b600e81526d312e382e31342d6532633132653760901b60208201526040519182916020835260208301906112a8565b5034610136578060031936011261013657610c86611e15565b60045460ff8160a01c1615610c99575080f35b60ff60a01b1916600160a01b176004557f547ced8bfaeeb516dd99a65ffc844c3eacbdc19ce3857d1bd0fc8108207c68088180a180f35b610775610d2a610cdf36611245565b6040516001600160a01b039182168152919492939291908416906020808401359187917f14beba1e8723c2a6b7a4cc9576347da53f1b79e39366f0d4f8b7a6af344eb71f91a4611804565b604051918291826112e9565b50610df8610d4336611245565b959294908394929450604094855196610d5c8789611349565b60018852601f19870194853660208b0137875195610d7a8988611349565b6001875236602088013783610d8e8a61160c565b52610dc7610d9b8761160c565b9960018060a01b038516809b52610db98a5198899260208401611680565b03601f198101885287611349565b60208101359889857f7f05232b74f48d98d9bbe9ff47315e5848c38ba5083076d84d1f6d67002df73b8a80a4611804565b600454845191956001600160a01b0390911692906020610e188185611349565b858452843b1561085e57865163060543e560e51b815263ffffffff90921660048301526001600160a01b039098166024820152608060448201528251608482018190529097859489949093600584901b860160a49081019491939283019290889088015b8b848310610ee057505050505050610ea2849283926003198483030160648501526112a8565b039134905af1938415610ed45761077594610ec4575b505051918291826112e9565b81610ece91611349565b38610eb8565b509051903d90823e3d90fd5b8396989a508060608594979b9981610f29948e600199979a9d60a319908503018b525163ffffffff8151168452898060a01b0388820151168885015201519382015201906112a8565b98019201920192889795938c97959293610e7c565b5034610136578060031936011261013657602060ff60045460a01c166040519015158152f35b50346101365760a0366003190112610136576044356001600160401b03811161086257610f9590369060040161139b565b90606435906001600160401b038211610136576020610fcf84610fbb366004870161139b565b610fc36111d4565b91602435600435611492565b604051908152f35b503461013657602036600319011261013657602090600435815260018252604060018060a01b0391205416604051908152f35b506110f18161107c61101b36611245565b9194939690602095604051946110318887611349565b8886526110eb6040998a966110ae8b6110a08a8981519e8f6110538482611349565b60018152601f19840180368884013761106e85519586611349565b60018552368786013761160c565b526110868161160c565b6001600160a01b038a16908190529b519d8e938401611680565b03601f1981018c528b611349565b6001600160a01b0316978c8b01359788877f15299a9532f9e616b46fb1fff3ff56426e75c2cab158a32a4cae83547bfa3f748580a4898989611492565b99611804565b95478181106111c057908882828896959411611183575b505063ffffffff9060018060a01b03600354169261113c89519788968795869463fa31de0160e01b8652166004850161146d565b03925af1801561117957610775955061115b57505051918291826112e9565b8161117192903d106103cb576103bc8183611349565b503880610eb8565b83513d87823e3d90fd5b829394955081611195819482936116e0565b335af16111a0611703565b50156111b157908492918838611108565b633d2cec6f60e21b8852600488fd5b63131398d760e21b89526004829052602489fd5b608435906001600160a01b03821682036111ea57565b600080fd5b600435906001600160a01b03821682036111ea57565b604435906001600160a01b03821682036111ea57565b602435906001600160a01b03821682036111ea57565b35906001600160a01b03821682036111ea57565b60a06003198201126111ea57600435906001600160401b0382116111ea5760c09082900360031901126111ea5760040190602435906044356001600160a01b03811681036111ea5790606435906084356001600160a01b03811681036111ea5790565b919082519283825260005b8481106112d4575050826000602080949584010152601f8019910116010190565b806020809284010151828286010152016112b3565b602081016020825282518091526040820191602060408360051b8301019401926000915b83831061131c57505050505090565b909192939460208061133a600193603f1986820301875289516112a8565b9701930193019193929061130d565b90601f801991011681019081106001600160401b0382111761136a57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161136a57601f01601f191660200190565b81601f820112156111ea578035906113b282611380565b926113c06040519485611349565b828452602083830101116111ea57816000926020809301838601378301015290565b9181601f840112156111ea578235916001600160401b0383116111ea576020808501948460051b0101116111ea57565b908160209103126111ea575190565b939060809361145d9363ffffffff61144f93999899168752602087015260a0604087015260a08601906112a8565b9084820360608601526112a8565b6001600160a01b03909416910152565b61148f939263ffffffff606093168252602082015281604082015201906112a8565b90565b600094929391929091906001600160a01b031680611534575050602092935063ffffffff60018060a01b0360035416916114e36040519687958694859463138857a360e31b8652166004850161146d565b03915afa908115611528576000916114f9575090565b90506020813d602011611520575b8161151460209383611349565b810103126111ea575190565b3d9150611507565b6040513d6000823e3d90fd5b6003546040516381d2ea9560e01b81529560209587956001600160a01b0390931694869485946115709491939063ffffffff1660048701611421565b03915afa9182156115b757809261158657505090565b9091506020823d6020116115af575b816115a260209383611349565b8101031261013657505190565b3d9150611595565b604051903d90823e3d90fd5b6001600160401b03811161136a5760051b60200190565b906115e4826115c3565b6115f16040519182611349565b8281528092611602601f19916115c3565b0190602036910137565b8051156116195760200190565b634e487b7160e01b600052603260045260246000fd5b80518210156116195760209160051b010190565b906020808351928381520192019060005b8181106116615750505090565b82516001600160a01b0316845260209384019390920191600101611654565b9291604084019360408152825180955260206060820193016000955b8087106116b857505061148f9394506020818403910152611643565b9093602080600192875181520195019601959061169c565b91908110156116195760051b0190565b919082039182116116ed57565b634e487b7160e01b600052601160045260246000fd5b3d1561172e573d9061171482611380565b916117226040519384611349565b82523d6000602084013e565b606090565b908060209392818452848401376000828201840152601f01601f1916010190565b356001600160a01b03811681036111ea5790565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea57602001918160061b360383136111ea57565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea57602001918160051b360383136111ea57565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea576020019181360383136111ea57565b919260ff60045460a01c161580611dfc575b611de757604051916020830191602083526101008401958535604086015260208601359283606087015260408701356080870152606087019460018060a01b0361185f87611231565b1660a08801526080880196873599601e198a3603019a8b8112156111ea578a01602081359101916001600160401b0382116111ea578160061b360383136111ea57819060c080860152526101208301919060005b818110611db75750505060a08a019a8b35908112156111ea578a0190813560208301926001600160401b0382116111ea578160051b9081360385136111ea57603f198685030160e08701528284528593602092810183019392810191600091607e193683900301905b858410611d125750505050505061193c925003601f198101835282611349565b51902090604051906020820192835260408201526040815261195f606082611349565b5190209361196c81611754565b306001600160a01b0390911603611ce85750818403611cd3576000848152600160205260409020546001600160a01b0316611cbe576001600160a01b0316928315611cad5760005260016020526040600020836bffffffffffffffffffffffff60a01b8254161790557f306cd1d43c9d25bf2e05db32b00e823b089fe9679696922daaba4c7093df9693600080a4611a048183611768565b91905060005b828110611bab57505050611a1e828261179d565b929050611a2a836115c3565b92611a386040519485611349565b808452611a47601f19916115c3565b0160005b818110611b9a57505060005b611a61828461179d565b9050811015611b9457611a74828461179d565b821015611619578160051b81013590605e19813603018212156111ea5701611a9b81611754565b6003546001600160a01b03918216911614611b8357611ab981611754565b906040810135600080602084019483611ad287876117d2565b9190826040519384928337810185815203925af192611aef611703565b9315611b185750505090600191611b06828761162f565b52611b11818661162f565b5001611a57565b90611b6893611b33611b7f93611b2d86611754565b956117d2565b604051630978ad9160e11b81526001600160a01b03909616600487015260806024870152949586959091608487019190611733565b9160448501526003198483030160648501526112a8565b0390fd5b631564d33760e31b60005260046000fd5b50505090565b806060602080938801015201611a4b565b611bb58285611768565b821015611619578160061b016040813603126111ea576040519060408201918083106001600160401b0384111761136a576000611c5992819260209560405285611bfe83611231565b928383520135958691015260018060a01b03169360405160208101916323b872dd60e01b8352336024830152306044830152606482015260648152611c44608482611349565b519082865af1611c52611703565b9083611e3e565b8051908115159182611c89575b5050611c755750600101611a0a565b635274afe760e01b60005260045260246000fd5b81925090602091810103126111ea57602001518015908115036111ea573880611c66565b6334d9914d60e11b60005260046000fd5b8363373d207960e01b60005260045260246000fd5b506344d659bf60e01b60005260045260246000fd5b611cf190611754565b631c26f26d60e01b60009081526001600160a01b0391909116600452602490fd5b9193959092949650601f198282030186528735838112156111ea5784016001600160a01b03611d4360208301611231565b1682526040810135603e1936839003018112156111ea5781602091010190602082359201906001600160401b0383116111ea5782360382136111ea578360406060611d9d602096958796838860019b015283860191611733565b93013591015299019601940191889694939197959761191c565b909192604080600192838060a01b03611dcf88611231565b168152602087810135908201520194019291016118b3565b63c37cea4760e01b6000523360045260246000fd5b5033600052600260205260ff6040600020541615611816565b6000546001600160a01b03163303611e2957565b63118cdaa760e01b6000523360045260246000fd5b90611e645750805115611e5357805190602001fd5b630a12f52160e11b60005260046000fd5b81511580611e96575b611e75575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b15611e6d56fea2646970667358221220b74e37263cc81ca15e9af2812a05b81be97cf375900563b98ae5576fc9152a9164736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.