Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
23680454 | 26 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
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"}]
Contract Creation Code
6080604052346101c85761211c80380380610019816101e3565b9283398101906060818303126101c85761003281610208565b6020820151918215158093036101c8576040810151906001600160401b0382116101c857019280601f850112156101c8578351936001600160401b0385116101cd578460051b906020806100878185016101e3565b8098815201928201019283116101c857602001905b8282106101b0575050506001600160a01b0316801561019a57600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36004805460ff60a01b191660a09290921b60ff60a01b1691909117905560005b815181101561018b576001906001600160a01b03610134828561021c565b5116600052600260205260406000208260ff1982541617905581808060a01b0361015e838661021c565b51167f3f3a0c23a11da402767747df1ed29891ffc0a54d42f3e8c767548cd45b7dd678600080a301610116565b604051611ed590816102478239f35b631e4fbdf760e01b600052600060045260246000fd5b602080916101bd84610208565b81520191019061009c565b600080fd5b634e487b7160e01b600052604160045260246000fd5b6040519190601f01601f191682016001600160401b038111838210176101cd57604052565b51906001600160a01b03821682036101c857565b80518210156102305760209160051b010190565b634e487b7160e01b600052603260045260246000fdfe6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c806327048b0f1461100a5780632aa91bfd14610fd75780632c16840214610f6457806340f3a5a814610f3e5780634667d3e514610d365780634a0e9d3a14610cd057806350b8452614610c6d57806354fd4d5014610c1b57806362b3a77c14610bdc578063715018a614610b825780637e0bdf8c14610af75780638da5cb5b14610ad0578063a0de4bbb14610866578063b15e2e9c146105ab578063c0d786551461052d578063caae303c146104b4578063d5438eae1461048b578063e1312bb71461023d578063f2fde38b146101b7578063f3c61d6b146101395763f887ea401461010e575061000e565b346101365780600319360112610136576004546040516001600160a01b039091168152602090f35b80fd5b5034610136576020366003190112610136576101536111ef565b61015b611e15565b600354906001600160a01b03821615610172578280f35b6001600160a01b03166001600160a01b03199190911681176003557f7a61e573722ff8b205c8962b59d37e7d30573f368965597a844a94872204ebd78280a238808280f35b5034610136576020366003190112610136576101d16111ef565b6101d9611e15565b6001600160a01b031680156102295781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b506060366003190112610136576004359061025661121b565b6044356001600160401b038111610487576102759036906004016113e2565b9390602092604051906102888583611349565b858252610294876115da565b96865b81811061042e57506040519697959694958895946001600160fb1b03831161042a5787958360051b9181838281943780838101039020946040519a8b967fd6383b4658ff90fe5c7fb8d1fe7a0b6cc87b7ecaf49d2305c1fed682f39548328c80a36040868d0152606086015260808501378201601f1983820360800101604084015260800161032591611643565b03601f19810186526103379086611349565b6001600160a01b03169261034d91858585611492565b80341061041857908185939234116103dd575b63ffffffff9060018060a01b0360035416926103936040519788968795869463fa31de0160e01b8652166004850161146d565b03925af180156103d2576103a5578280f35b816103c492903d106103cb575b6103bc8183611349565b810190611412565b5038808280f35b503d6103b2565b6040513d85823e3d90fd5b90919250858080806103ef85346116e0565b335af16103fa611703565b50156104095790849291610360565b633d2cec6f60e21b8652600486fd5b63131398d760e21b8652600452602485fd5b8680fd5b6104398183876116d0565b3588526001875260408820546001600160a01b031680156104695790600191610462828c61162f565b5201610297565b60248961047784868a6116d0565b636d5ba68f60e11b825235600452fd5b8280fd5b50346101365780600319360112610136576003546040516001600160a01b039091168152602090f35b5034610136576040366003190112610136576104ce6111ef565b60243590811515809203610487576104e4611e15565b6001600160a01b0316808352600260205260408320805460ff191660ff84161790557f3f3a0c23a11da402767747df1ed29891ffc0a54d42f3e8c767548cd45b7dd6788380a380f35b5034610136576020366003190112610136576105476111ef565b61054f611e15565b600454906001600160a01b03821615610566578280f35b6001600160a01b03166001600160a01b03199190911681176004557fc6b438e6a8a59579ce6a4406cbd203b740e0d47b458aae6596339bcd40c40d158280a238808280f35b5060e0366003190112610136576004356001600160401b0381116108625760c06003198236030112610862576105df611205565b906064356105eb6111d4565b60a4356001600160401b03811161085e5761060a90369060040161139b565b60c4356001600160a01b0381169590939086850361085a57604095828751966106338989611349565b60018852601f19890196873660208b01378951976106518b8a611349565b600189523660208a0137826106658a61160c565b5261066f8861160c565b6001600160a01b038616908190528a519990988a91610692919060208401611680565b03601f1981018a526106a4908a611349565b6001600160a01b03169660248401359586907f15299a9532f9e616b46fb1fff3ff56426e75c2cab158a32a4cae83547bfa3f748e80a46106e79086898988611492565b926106f89260243590600401611804565b96478281106108465780838b9211610812575b50509081602095949392156000146107a25750600354875163fa31de0160e01b81529687956001600160a01b03909216945085938492610755929163ffffffff166004850161146d565b03925af18015610798576107759450610779575b505b51918291826112e9565b0390f35b6107919060203d6020116103cb576103bc8183611349565b5038610769565b82513d86823e3d90fd5b60035488516242e0f760e61b81529788966001600160a01b0390921695879586946107d99490939163ffffffff1660048701611421565b03925af180156107985761077594506107f3575b5061076b565b61080b9060203d6020116103cb576103bc8183611349565b50386107ed565b818061081f8682946116e0565b335af161082a611703565b501561083757883861070b565b633d2cec6f60e21b8952600489fd5b63131398d760e21b8a52600483905260248afd5b8780fd5b8580fd5b5080fd5b5060a03660031901126101365760043561087e61121b565b916044356001600160401b0381116108625761089e9036906004016113e2565b9290936064356001600160401b038111610acc576108c090369060040161139b565b906108c96111d4565b946108d3816115da565b96855b828110610a825750604051916001600160fb1b03811161042a57869798608087610970957fd6383b4658ff90fe5c7fb8d1fe7a0b6cc87b7ecaf49d2305c1fed682f39548329a95856109629660051b93838584819637808581010390206040519e8f9a80a36040602089015260608801528387013784018481038201601f190160408601520190611643565b03601f198101865285611349565b6001600160a01b0316916109878683868685611492565b80341061041857803411610a55575b949593946020946001600160a01b031680610a1d575060035460405163fa31de0160e01b81529687956001600160a01b039092169450859384926109e4929163ffffffff166004850161146d565b03925af18015610a12576109f6575080f35b610a0e9060203d6020116103cb576103bc8183611349565b5080f35b6040513d84823e3d90fd5b6003546040516242e0f760e61b81529788966001600160a01b0390921695879586946109e49490939163ffffffff1660048701611421565b85808080610a6385346116e0565b335af1610a6e611703565b5061099657633d2cec6f60e21b8652600486fd5b610a8d8184846116d0565b358752600160205260408720546001600160a01b03168015610abe5790600191610ab7828c61162f565b52016108d6565b6024886104778487876116d0565b8380fd5b5034610136578060031936011261013657546040516001600160a01b039091168152602090f35b506080366003190112610136576004356001600160401b0381116108625760c0600319823603011261086257610775602492610b31611205565b9260643591610b468386883585600401611804565b927f160fbf39d03c171cfc82812374f495fff22339e6f2482ce8366139b1710d003b60405197889760018060a01b03169401359280a4826112e9565b5034610136578060031936011261013657610b9b611e15565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101365760203660031901126101365760209060ff906040906001600160a01b03610c076111ef565b168152600284522054166040519015158152f35b503461013657806003193601126101365750610775604051610c3e604082611349565b600e81526d312e382e31342d6532633132653760901b60208201526040519182916020835260208301906112a8565b5034610136578060031936011261013657610c86611e15565b60045460ff8160a01c1615610c99575080f35b60ff60a01b1916600160a01b176004557f547ced8bfaeeb516dd99a65ffc844c3eacbdc19ce3857d1bd0fc8108207c68088180a180f35b610775610d2a610cdf36611245565b6040516001600160a01b039182168152919492939291908416906020808401359187917f14beba1e8723c2a6b7a4cc9576347da53f1b79e39366f0d4f8b7a6af344eb71f91a4611804565b604051918291826112e9565b50610df8610d4336611245565b959294908394929450604094855196610d5c8789611349565b60018852601f19870194853660208b0137875195610d7a8988611349565b6001875236602088013783610d8e8a61160c565b52610dc7610d9b8761160c565b9960018060a01b038516809b52610db98a5198899260208401611680565b03601f198101885287611349565b60208101359889857f7f05232b74f48d98d9bbe9ff47315e5848c38ba5083076d84d1f6d67002df73b8a80a4611804565b600454845191956001600160a01b0390911692906020610e188185611349565b858452843b1561085e57865163060543e560e51b815263ffffffff90921660048301526001600160a01b039098166024820152608060448201528251608482018190529097859489949093600584901b860160a49081019491939283019290889088015b8b848310610ee057505050505050610ea2849283926003198483030160648501526112a8565b039134905af1938415610ed45761077594610ec4575b505051918291826112e9565b81610ece91611349565b38610eb8565b509051903d90823e3d90fd5b8396989a508060608594979b9981610f29948e600199979a9d60a319908503018b525163ffffffff8151168452898060a01b0388820151168885015201519382015201906112a8565b98019201920192889795938c97959293610e7c565b5034610136578060031936011261013657602060ff60045460a01c166040519015158152f35b50346101365760a0366003190112610136576044356001600160401b03811161086257610f9590369060040161139b565b90606435906001600160401b038211610136576020610fcf84610fbb366004870161139b565b610fc36111d4565b91602435600435611492565b604051908152f35b503461013657602036600319011261013657602090600435815260018252604060018060a01b0391205416604051908152f35b506110f18161107c61101b36611245565b9194939690602095604051946110318887611349565b8886526110eb6040998a966110ae8b6110a08a8981519e8f6110538482611349565b60018152601f19840180368884013761106e85519586611349565b60018552368786013761160c565b526110868161160c565b6001600160a01b038a16908190529b519d8e938401611680565b03601f1981018c528b611349565b6001600160a01b0316978c8b01359788877f15299a9532f9e616b46fb1fff3ff56426e75c2cab158a32a4cae83547bfa3f748580a4898989611492565b99611804565b95478181106111c057908882828896959411611183575b505063ffffffff9060018060a01b03600354169261113c89519788968795869463fa31de0160e01b8652166004850161146d565b03925af1801561117957610775955061115b57505051918291826112e9565b8161117192903d106103cb576103bc8183611349565b503880610eb8565b83513d87823e3d90fd5b829394955081611195819482936116e0565b335af16111a0611703565b50156111b157908492918838611108565b633d2cec6f60e21b8852600488fd5b63131398d760e21b89526004829052602489fd5b608435906001600160a01b03821682036111ea57565b600080fd5b600435906001600160a01b03821682036111ea57565b604435906001600160a01b03821682036111ea57565b602435906001600160a01b03821682036111ea57565b35906001600160a01b03821682036111ea57565b60a06003198201126111ea57600435906001600160401b0382116111ea5760c09082900360031901126111ea5760040190602435906044356001600160a01b03811681036111ea5790606435906084356001600160a01b03811681036111ea5790565b919082519283825260005b8481106112d4575050826000602080949584010152601f8019910116010190565b806020809284010151828286010152016112b3565b602081016020825282518091526040820191602060408360051b8301019401926000915b83831061131c57505050505090565b909192939460208061133a600193603f1986820301875289516112a8565b9701930193019193929061130d565b90601f801991011681019081106001600160401b0382111761136a57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161136a57601f01601f191660200190565b81601f820112156111ea578035906113b282611380565b926113c06040519485611349565b828452602083830101116111ea57816000926020809301838601378301015290565b9181601f840112156111ea578235916001600160401b0383116111ea576020808501948460051b0101116111ea57565b908160209103126111ea575190565b939060809361145d9363ffffffff61144f93999899168752602087015260a0604087015260a08601906112a8565b9084820360608601526112a8565b6001600160a01b03909416910152565b61148f939263ffffffff606093168252602082015281604082015201906112a8565b90565b600094929391929091906001600160a01b031680611534575050602092935063ffffffff60018060a01b0360035416916114e36040519687958694859463138857a360e31b8652166004850161146d565b03915afa908115611528576000916114f9575090565b90506020813d602011611520575b8161151460209383611349565b810103126111ea575190565b3d9150611507565b6040513d6000823e3d90fd5b6003546040516381d2ea9560e01b81529560209587956001600160a01b0390931694869485946115709491939063ffffffff1660048701611421565b03915afa9182156115b757809261158657505090565b9091506020823d6020116115af575b816115a260209383611349565b8101031261013657505190565b3d9150611595565b604051903d90823e3d90fd5b6001600160401b03811161136a5760051b60200190565b906115e4826115c3565b6115f16040519182611349565b8281528092611602601f19916115c3565b0190602036910137565b8051156116195760200190565b634e487b7160e01b600052603260045260246000fd5b80518210156116195760209160051b010190565b906020808351928381520192019060005b8181106116615750505090565b82516001600160a01b0316845260209384019390920191600101611654565b9291604084019360408152825180955260206060820193016000955b8087106116b857505061148f9394506020818403910152611643565b9093602080600192875181520195019601959061169c565b91908110156116195760051b0190565b919082039182116116ed57565b634e487b7160e01b600052601160045260246000fd5b3d1561172e573d9061171482611380565b916117226040519384611349565b82523d6000602084013e565b606090565b908060209392818452848401376000828201840152601f01601f1916010190565b356001600160a01b03811681036111ea5790565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea57602001918160061b360383136111ea57565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea57602001918160051b360383136111ea57565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea576020019181360383136111ea57565b919260ff60045460a01c161580611dfc575b611de757604051916020830191602083526101008401958535604086015260208601359283606087015260408701356080870152606087019460018060a01b0361185f87611231565b1660a08801526080880196873599601e198a3603019a8b8112156111ea578a01602081359101916001600160401b0382116111ea578160061b360383136111ea57819060c080860152526101208301919060005b818110611db75750505060a08a019a8b35908112156111ea578a0190813560208301926001600160401b0382116111ea578160051b9081360385136111ea57603f198685030160e08701528284528593602092810183019392810191600091607e193683900301905b858410611d125750505050505061193c925003601f198101835282611349565b51902090604051906020820192835260408201526040815261195f606082611349565b5190209361196c81611754565b306001600160a01b0390911603611ce85750818403611cd3576000848152600160205260409020546001600160a01b0316611cbe576001600160a01b0316928315611cad5760005260016020526040600020836bffffffffffffffffffffffff60a01b8254161790557f306cd1d43c9d25bf2e05db32b00e823b089fe9679696922daaba4c7093df9693600080a4611a048183611768565b91905060005b828110611bab57505050611a1e828261179d565b929050611a2a836115c3565b92611a386040519485611349565b808452611a47601f19916115c3565b0160005b818110611b9a57505060005b611a61828461179d565b9050811015611b9457611a74828461179d565b821015611619578160051b81013590605e19813603018212156111ea5701611a9b81611754565b6003546001600160a01b03918216911614611b8357611ab981611754565b906040810135600080602084019483611ad287876117d2565b9190826040519384928337810185815203925af192611aef611703565b9315611b185750505090600191611b06828761162f565b52611b11818661162f565b5001611a57565b90611b6893611b33611b7f93611b2d86611754565b956117d2565b604051630978ad9160e11b81526001600160a01b03909616600487015260806024870152949586959091608487019190611733565b9160448501526003198483030160648501526112a8565b0390fd5b631564d33760e31b60005260046000fd5b50505090565b806060602080938801015201611a4b565b611bb58285611768565b821015611619578160061b016040813603126111ea576040519060408201918083106001600160401b0384111761136a576000611c5992819260209560405285611bfe83611231565b928383520135958691015260018060a01b03169360405160208101916323b872dd60e01b8352336024830152306044830152606482015260648152611c44608482611349565b519082865af1611c52611703565b9083611e3e565b8051908115159182611c89575b5050611c755750600101611a0a565b635274afe760e01b60005260045260246000fd5b81925090602091810103126111ea57602001518015908115036111ea573880611c66565b6334d9914d60e11b60005260046000fd5b8363373d207960e01b60005260045260246000fd5b506344d659bf60e01b60005260045260246000fd5b611cf190611754565b631c26f26d60e01b60009081526001600160a01b0391909116600452602490fd5b9193959092949650601f198282030186528735838112156111ea5784016001600160a01b03611d4360208301611231565b1682526040810135603e1936839003018112156111ea5781602091010190602082359201906001600160401b0383116111ea5782360382136111ea578360406060611d9d602096958796838860019b015283860191611733565b93013591015299019601940191889694939197959761191c565b909192604080600192838060a01b03611dcf88611231565b168152602087810135908201520194019291016118b3565b63c37cea4760e01b6000523360045260246000fd5b5033600052600260205260ff6040600020541615611816565b6000546001600160a01b03163303611e2957565b63118cdaa760e01b6000523360045260246000fd5b90611e645750805115611e5357805190602001fd5b630a12f52160e11b60005260046000fd5b81511580611e96575b611e75575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b15611e6d56fea2646970667358221220b74e37263cc81ca15e9af2812a05b81be97cf375900563b98ae5576fc9152a9164736f6c634300081a0033000000000000000000000000791d7d397a3cc4134dc6471f0ecc496a61ffc2850000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007b65dd8dad147c5dba896a7c062a477a11a5ed5e
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b6000803560e01c806327048b0f1461100a5780632aa91bfd14610fd75780632c16840214610f6457806340f3a5a814610f3e5780634667d3e514610d365780634a0e9d3a14610cd057806350b8452614610c6d57806354fd4d5014610c1b57806362b3a77c14610bdc578063715018a614610b825780637e0bdf8c14610af75780638da5cb5b14610ad0578063a0de4bbb14610866578063b15e2e9c146105ab578063c0d786551461052d578063caae303c146104b4578063d5438eae1461048b578063e1312bb71461023d578063f2fde38b146101b7578063f3c61d6b146101395763f887ea401461010e575061000e565b346101365780600319360112610136576004546040516001600160a01b039091168152602090f35b80fd5b5034610136576020366003190112610136576101536111ef565b61015b611e15565b600354906001600160a01b03821615610172578280f35b6001600160a01b03166001600160a01b03199190911681176003557f7a61e573722ff8b205c8962b59d37e7d30573f368965597a844a94872204ebd78280a238808280f35b5034610136576020366003190112610136576101d16111ef565b6101d9611e15565b6001600160a01b031680156102295781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b506060366003190112610136576004359061025661121b565b6044356001600160401b038111610487576102759036906004016113e2565b9390602092604051906102888583611349565b858252610294876115da565b96865b81811061042e57506040519697959694958895946001600160fb1b03831161042a5787958360051b9181838281943780838101039020946040519a8b967fd6383b4658ff90fe5c7fb8d1fe7a0b6cc87b7ecaf49d2305c1fed682f39548328c80a36040868d0152606086015260808501378201601f1983820360800101604084015260800161032591611643565b03601f19810186526103379086611349565b6001600160a01b03169261034d91858585611492565b80341061041857908185939234116103dd575b63ffffffff9060018060a01b0360035416926103936040519788968795869463fa31de0160e01b8652166004850161146d565b03925af180156103d2576103a5578280f35b816103c492903d106103cb575b6103bc8183611349565b810190611412565b5038808280f35b503d6103b2565b6040513d85823e3d90fd5b90919250858080806103ef85346116e0565b335af16103fa611703565b50156104095790849291610360565b633d2cec6f60e21b8652600486fd5b63131398d760e21b8652600452602485fd5b8680fd5b6104398183876116d0565b3588526001875260408820546001600160a01b031680156104695790600191610462828c61162f565b5201610297565b60248961047784868a6116d0565b636d5ba68f60e11b825235600452fd5b8280fd5b50346101365780600319360112610136576003546040516001600160a01b039091168152602090f35b5034610136576040366003190112610136576104ce6111ef565b60243590811515809203610487576104e4611e15565b6001600160a01b0316808352600260205260408320805460ff191660ff84161790557f3f3a0c23a11da402767747df1ed29891ffc0a54d42f3e8c767548cd45b7dd6788380a380f35b5034610136576020366003190112610136576105476111ef565b61054f611e15565b600454906001600160a01b03821615610566578280f35b6001600160a01b03166001600160a01b03199190911681176004557fc6b438e6a8a59579ce6a4406cbd203b740e0d47b458aae6596339bcd40c40d158280a238808280f35b5060e0366003190112610136576004356001600160401b0381116108625760c06003198236030112610862576105df611205565b906064356105eb6111d4565b60a4356001600160401b03811161085e5761060a90369060040161139b565b60c4356001600160a01b0381169590939086850361085a57604095828751966106338989611349565b60018852601f19890196873660208b01378951976106518b8a611349565b600189523660208a0137826106658a61160c565b5261066f8861160c565b6001600160a01b038616908190528a519990988a91610692919060208401611680565b03601f1981018a526106a4908a611349565b6001600160a01b03169660248401359586907f15299a9532f9e616b46fb1fff3ff56426e75c2cab158a32a4cae83547bfa3f748e80a46106e79086898988611492565b926106f89260243590600401611804565b96478281106108465780838b9211610812575b50509081602095949392156000146107a25750600354875163fa31de0160e01b81529687956001600160a01b03909216945085938492610755929163ffffffff166004850161146d565b03925af18015610798576107759450610779575b505b51918291826112e9565b0390f35b6107919060203d6020116103cb576103bc8183611349565b5038610769565b82513d86823e3d90fd5b60035488516242e0f760e61b81529788966001600160a01b0390921695879586946107d99490939163ffffffff1660048701611421565b03925af180156107985761077594506107f3575b5061076b565b61080b9060203d6020116103cb576103bc8183611349565b50386107ed565b818061081f8682946116e0565b335af161082a611703565b501561083757883861070b565b633d2cec6f60e21b8952600489fd5b63131398d760e21b8a52600483905260248afd5b8780fd5b8580fd5b5080fd5b5060a03660031901126101365760043561087e61121b565b916044356001600160401b0381116108625761089e9036906004016113e2565b9290936064356001600160401b038111610acc576108c090369060040161139b565b906108c96111d4565b946108d3816115da565b96855b828110610a825750604051916001600160fb1b03811161042a57869798608087610970957fd6383b4658ff90fe5c7fb8d1fe7a0b6cc87b7ecaf49d2305c1fed682f39548329a95856109629660051b93838584819637808581010390206040519e8f9a80a36040602089015260608801528387013784018481038201601f190160408601520190611643565b03601f198101865285611349565b6001600160a01b0316916109878683868685611492565b80341061041857803411610a55575b949593946020946001600160a01b031680610a1d575060035460405163fa31de0160e01b81529687956001600160a01b039092169450859384926109e4929163ffffffff166004850161146d565b03925af18015610a12576109f6575080f35b610a0e9060203d6020116103cb576103bc8183611349565b5080f35b6040513d84823e3d90fd5b6003546040516242e0f760e61b81529788966001600160a01b0390921695879586946109e49490939163ffffffff1660048701611421565b85808080610a6385346116e0565b335af1610a6e611703565b5061099657633d2cec6f60e21b8652600486fd5b610a8d8184846116d0565b358752600160205260408720546001600160a01b03168015610abe5790600191610ab7828c61162f565b52016108d6565b6024886104778487876116d0565b8380fd5b5034610136578060031936011261013657546040516001600160a01b039091168152602090f35b506080366003190112610136576004356001600160401b0381116108625760c0600319823603011261086257610775602492610b31611205565b9260643591610b468386883585600401611804565b927f160fbf39d03c171cfc82812374f495fff22339e6f2482ce8366139b1710d003b60405197889760018060a01b03169401359280a4826112e9565b5034610136578060031936011261013657610b9b611e15565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101365760203660031901126101365760209060ff906040906001600160a01b03610c076111ef565b168152600284522054166040519015158152f35b503461013657806003193601126101365750610775604051610c3e604082611349565b600e81526d312e382e31342d6532633132653760901b60208201526040519182916020835260208301906112a8565b5034610136578060031936011261013657610c86611e15565b60045460ff8160a01c1615610c99575080f35b60ff60a01b1916600160a01b176004557f547ced8bfaeeb516dd99a65ffc844c3eacbdc19ce3857d1bd0fc8108207c68088180a180f35b610775610d2a610cdf36611245565b6040516001600160a01b039182168152919492939291908416906020808401359187917f14beba1e8723c2a6b7a4cc9576347da53f1b79e39366f0d4f8b7a6af344eb71f91a4611804565b604051918291826112e9565b50610df8610d4336611245565b959294908394929450604094855196610d5c8789611349565b60018852601f19870194853660208b0137875195610d7a8988611349565b6001875236602088013783610d8e8a61160c565b52610dc7610d9b8761160c565b9960018060a01b038516809b52610db98a5198899260208401611680565b03601f198101885287611349565b60208101359889857f7f05232b74f48d98d9bbe9ff47315e5848c38ba5083076d84d1f6d67002df73b8a80a4611804565b600454845191956001600160a01b0390911692906020610e188185611349565b858452843b1561085e57865163060543e560e51b815263ffffffff90921660048301526001600160a01b039098166024820152608060448201528251608482018190529097859489949093600584901b860160a49081019491939283019290889088015b8b848310610ee057505050505050610ea2849283926003198483030160648501526112a8565b039134905af1938415610ed45761077594610ec4575b505051918291826112e9565b81610ece91611349565b38610eb8565b509051903d90823e3d90fd5b8396989a508060608594979b9981610f29948e600199979a9d60a319908503018b525163ffffffff8151168452898060a01b0388820151168885015201519382015201906112a8565b98019201920192889795938c97959293610e7c565b5034610136578060031936011261013657602060ff60045460a01c166040519015158152f35b50346101365760a0366003190112610136576044356001600160401b03811161086257610f9590369060040161139b565b90606435906001600160401b038211610136576020610fcf84610fbb366004870161139b565b610fc36111d4565b91602435600435611492565b604051908152f35b503461013657602036600319011261013657602090600435815260018252604060018060a01b0391205416604051908152f35b506110f18161107c61101b36611245565b9194939690602095604051946110318887611349565b8886526110eb6040998a966110ae8b6110a08a8981519e8f6110538482611349565b60018152601f19840180368884013761106e85519586611349565b60018552368786013761160c565b526110868161160c565b6001600160a01b038a16908190529b519d8e938401611680565b03601f1981018c528b611349565b6001600160a01b0316978c8b01359788877f15299a9532f9e616b46fb1fff3ff56426e75c2cab158a32a4cae83547bfa3f748580a4898989611492565b99611804565b95478181106111c057908882828896959411611183575b505063ffffffff9060018060a01b03600354169261113c89519788968795869463fa31de0160e01b8652166004850161146d565b03925af1801561117957610775955061115b57505051918291826112e9565b8161117192903d106103cb576103bc8183611349565b503880610eb8565b83513d87823e3d90fd5b829394955081611195819482936116e0565b335af16111a0611703565b50156111b157908492918838611108565b633d2cec6f60e21b8852600488fd5b63131398d760e21b89526004829052602489fd5b608435906001600160a01b03821682036111ea57565b600080fd5b600435906001600160a01b03821682036111ea57565b604435906001600160a01b03821682036111ea57565b602435906001600160a01b03821682036111ea57565b35906001600160a01b03821682036111ea57565b60a06003198201126111ea57600435906001600160401b0382116111ea5760c09082900360031901126111ea5760040190602435906044356001600160a01b03811681036111ea5790606435906084356001600160a01b03811681036111ea5790565b919082519283825260005b8481106112d4575050826000602080949584010152601f8019910116010190565b806020809284010151828286010152016112b3565b602081016020825282518091526040820191602060408360051b8301019401926000915b83831061131c57505050505090565b909192939460208061133a600193603f1986820301875289516112a8565b9701930193019193929061130d565b90601f801991011681019081106001600160401b0382111761136a57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161136a57601f01601f191660200190565b81601f820112156111ea578035906113b282611380565b926113c06040519485611349565b828452602083830101116111ea57816000926020809301838601378301015290565b9181601f840112156111ea578235916001600160401b0383116111ea576020808501948460051b0101116111ea57565b908160209103126111ea575190565b939060809361145d9363ffffffff61144f93999899168752602087015260a0604087015260a08601906112a8565b9084820360608601526112a8565b6001600160a01b03909416910152565b61148f939263ffffffff606093168252602082015281604082015201906112a8565b90565b600094929391929091906001600160a01b031680611534575050602092935063ffffffff60018060a01b0360035416916114e36040519687958694859463138857a360e31b8652166004850161146d565b03915afa908115611528576000916114f9575090565b90506020813d602011611520575b8161151460209383611349565b810103126111ea575190565b3d9150611507565b6040513d6000823e3d90fd5b6003546040516381d2ea9560e01b81529560209587956001600160a01b0390931694869485946115709491939063ffffffff1660048701611421565b03915afa9182156115b757809261158657505090565b9091506020823d6020116115af575b816115a260209383611349565b8101031261013657505190565b3d9150611595565b604051903d90823e3d90fd5b6001600160401b03811161136a5760051b60200190565b906115e4826115c3565b6115f16040519182611349565b8281528092611602601f19916115c3565b0190602036910137565b8051156116195760200190565b634e487b7160e01b600052603260045260246000fd5b80518210156116195760209160051b010190565b906020808351928381520192019060005b8181106116615750505090565b82516001600160a01b0316845260209384019390920191600101611654565b9291604084019360408152825180955260206060820193016000955b8087106116b857505061148f9394506020818403910152611643565b9093602080600192875181520195019601959061169c565b91908110156116195760051b0190565b919082039182116116ed57565b634e487b7160e01b600052601160045260246000fd5b3d1561172e573d9061171482611380565b916117226040519384611349565b82523d6000602084013e565b606090565b908060209392818452848401376000828201840152601f01601f1916010190565b356001600160a01b03811681036111ea5790565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea57602001918160061b360383136111ea57565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea57602001918160051b360383136111ea57565b903590601e19813603018212156111ea57018035906001600160401b0382116111ea576020019181360383136111ea57565b919260ff60045460a01c161580611dfc575b611de757604051916020830191602083526101008401958535604086015260208601359283606087015260408701356080870152606087019460018060a01b0361185f87611231565b1660a08801526080880196873599601e198a3603019a8b8112156111ea578a01602081359101916001600160401b0382116111ea578160061b360383136111ea57819060c080860152526101208301919060005b818110611db75750505060a08a019a8b35908112156111ea578a0190813560208301926001600160401b0382116111ea578160051b9081360385136111ea57603f198685030160e08701528284528593602092810183019392810191600091607e193683900301905b858410611d125750505050505061193c925003601f198101835282611349565b51902090604051906020820192835260408201526040815261195f606082611349565b5190209361196c81611754565b306001600160a01b0390911603611ce85750818403611cd3576000848152600160205260409020546001600160a01b0316611cbe576001600160a01b0316928315611cad5760005260016020526040600020836bffffffffffffffffffffffff60a01b8254161790557f306cd1d43c9d25bf2e05db32b00e823b089fe9679696922daaba4c7093df9693600080a4611a048183611768565b91905060005b828110611bab57505050611a1e828261179d565b929050611a2a836115c3565b92611a386040519485611349565b808452611a47601f19916115c3565b0160005b818110611b9a57505060005b611a61828461179d565b9050811015611b9457611a74828461179d565b821015611619578160051b81013590605e19813603018212156111ea5701611a9b81611754565b6003546001600160a01b03918216911614611b8357611ab981611754565b906040810135600080602084019483611ad287876117d2565b9190826040519384928337810185815203925af192611aef611703565b9315611b185750505090600191611b06828761162f565b52611b11818661162f565b5001611a57565b90611b6893611b33611b7f93611b2d86611754565b956117d2565b604051630978ad9160e11b81526001600160a01b03909616600487015260806024870152949586959091608487019190611733565b9160448501526003198483030160648501526112a8565b0390fd5b631564d33760e31b60005260046000fd5b50505090565b806060602080938801015201611a4b565b611bb58285611768565b821015611619578160061b016040813603126111ea576040519060408201918083106001600160401b0384111761136a576000611c5992819260209560405285611bfe83611231565b928383520135958691015260018060a01b03169360405160208101916323b872dd60e01b8352336024830152306044830152606482015260648152611c44608482611349565b519082865af1611c52611703565b9083611e3e565b8051908115159182611c89575b5050611c755750600101611a0a565b635274afe760e01b60005260045260246000fd5b81925090602091810103126111ea57602001518015908115036111ea573880611c66565b6334d9914d60e11b60005260046000fd5b8363373d207960e01b60005260045260246000fd5b506344d659bf60e01b60005260045260246000fd5b611cf190611754565b631c26f26d60e01b60009081526001600160a01b0391909116600452602490fd5b9193959092949650601f198282030186528735838112156111ea5784016001600160a01b03611d4360208301611231565b1682526040810135603e1936839003018112156111ea5781602091010190602082359201906001600160401b0383116111ea5782360382136111ea578360406060611d9d602096958796838860019b015283860191611733565b93013591015299019601940191889694939197959761191c565b909192604080600192838060a01b03611dcf88611231565b168152602087810135908201520194019291016118b3565b63c37cea4760e01b6000523360045260246000fd5b5033600052600260205260ff6040600020541615611816565b6000546001600160a01b03163303611e2957565b63118cdaa760e01b6000523360045260246000fd5b90611e645750805115611e5357805190602001fd5b630a12f52160e11b60005260046000fd5b81511580611e96575b611e75575090565b639996b31560e01b60009081526001600160a01b0391909116600452602490fd5b50803b15611e6d56fea2646970667358221220b74e37263cc81ca15e9af2812a05b81be97cf375900563b98ae5576fc9152a9164736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000791d7d397a3cc4134dc6471f0ecc496a61ffc2850000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000007b65dd8dad147c5dba896a7c062a477a11a5ed5e
-----Decoded View---------------
Arg [0] : _owner (address): 0x791d7d397a3cC4134dC6471f0ecc496A61FFc285
Arg [1] : _isSolvingPublic (bool): True
Arg [2] : _solvers (address[]): 0x7b65Dd8dad147C5DBa896A7c062a477a11a5Ed5E
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000791d7d397a3cc4134dc6471f0ecc496a61ffc285
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000007b65dd8dad147c5dba896a7c062a477a11a5ed5e
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.