Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
L1CrossDomainMessengerFast
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 10000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; import { Lib_AddressManager } from "../../libraries/resolver/Lib_AddressManager.sol"; import { Lib_SecureMerkleTrie } from "../../libraries/trie/Lib_SecureMerkleTrie.sol"; import { Lib_DefaultValues } from "../../libraries/constants/Lib_DefaultValues.sol"; import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol"; import { Lib_CrossDomainUtils } from "../../libraries/bridge/Lib_CrossDomainUtils.sol"; /* Interface Imports */ import { IL1CrossDomainMessenger } from "./IL1CrossDomainMessenger.sol"; import { IStateCommitmentChain } from "../rollup/IStateCommitmentChain.sol"; /* External Imports */ // for security import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; /** * @title L1CrossDomainMessengerFast * @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages * from L2 onto L1. In the event that a message sent from L1 to L2 is rejected for exceeding the L2 * epoch gas limit, it can be resubmitted via this contract's replay function. * */ contract L1CrossDomainMessengerFast is IL1CrossDomainMessenger, Lib_AddressResolver, OwnableUpgradeable, PausableUpgradeable, ReentrancyGuardUpgradeable { /********** * Events * **********/ event MessageBlocked(bytes32 indexed _xDomainCalldataHash); event MessageAllowed(bytes32 indexed _xDomainCalldataHash); /********************** * Contract Variables * **********************/ mapping(bytes32 => bool) public blockedMessages; mapping(bytes32 => bool) public relayedMessages; mapping(bytes32 => bool) public successfulMessages; mapping(bytes32 => bool) public failedMessages; address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; /*************** * Constructor * ***************/ /** * This contract is intended to be behind a delegate proxy. * We pass the zero address to the address resolver just to satisfy the constructor. * We still need to set this value in initialize(). */ constructor() Lib_AddressResolver(address(0)) {} /********************** * Function Modifiers * **********************/ modifier onlyRelayer() { require( msg.sender == resolve("OVM_FastRelayer"), "L1CrossDomainMessengerFast: Function can only be called by the FastRelayer" ); _; } /******************** * Public Functions * ********************/ /** * @param _libAddressManager Address of the Address Manager. */ function initialize(address _libAddressManager) public initializer { require( address(libAddressManager) == address(0), "L1CrossDomainMessenger already intialized." ); libAddressManager = Lib_AddressManager(_libAddressManager); xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; // Initialize upgradable OZ contracts __Context_init_unchained(); // Context is a dependency for both Ownable and Pausable __Ownable_init_unchained(); __Pausable_init_unchained(); __ReentrancyGuard_init_unchained(); } /** * Pause fast exit relays */ function pause() external onlyOwner { _pause(); } /** * UnPause fast exit relays */ function unpause() external onlyOwner { _unpause(); } /** * Block a message. * @param _xDomainCalldataHash Hash of the message to block. */ function blockMessage(bytes32 _xDomainCalldataHash) external onlyOwner { blockedMessages[_xDomainCalldataHash] = true; emit MessageBlocked(_xDomainCalldataHash); } /** * Allow a message. * @param _xDomainCalldataHash Hash of the message to block. */ function allowMessage(bytes32 _xDomainCalldataHash) external onlyOwner { blockedMessages[_xDomainCalldataHash] = false; emit MessageAllowed(_xDomainCalldataHash); } function xDomainMessageSender() public view override returns (address) { require( xDomainMsgSender != Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER, "xDomainMessageSender is not set" ); return xDomainMsgSender; } /** * Sends a cross domain message to the target messenger. * @param _target Target contract address. * @param _message Message to send to the target. * @param _gasLimit Gas limit for the provided message. */ function sendMessage( address _target, bytes memory _message, uint32 _gasLimit ) public override { // refund gas and restore state revert("Sending via this messenger is disabled"); } /******************** * Public Functions * ********************/ /** * Relays a cross domain message to a contract. * @inheritdoc IL1CrossDomainMessenger */ function relayMessage( address _target, address _sender, bytes memory _message, uint256 _messageNonce, L2MessageInclusionProof memory _proof ) public override nonReentrant whenNotPaused { // generate calldata from params bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( _target, _sender, _message, _messageNonce ); // verify message state from xDomainCalldata and _proof require( _verifyXDomainMessage(xDomainCalldata, _proof) == true, "Provided message could not be verified." ); bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); require( successfulMessages[xDomainCalldataHash] == false, "Provided message has already been received." ); require( blockedMessages[xDomainCalldataHash] == false, "Provided message has been blocked." ); require( _target != resolve("CanonicalTransactionChain"), "Cannot send L2->L1 messages to L1 system contracts." ); xDomainMsgSender = _sender; // direct call from _message (bool success, ) = _target.call(_message); xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; // Mark the message as received if the call was successful. Ensures that a message can be // relayed multiple times in the case that the call reverted. if (success == true) { successfulMessages[xDomainCalldataHash] = true; emit RelayedFastMessage(_target, _sender, _message, _messageNonce); } else { failedMessages[xDomainCalldataHash] == true; emit FailedRelayedFastMessage(_target, _sender, _message, _messageNonce); } // Store an identifier that can be used to prove that the given message was relayed by some // user. Gives us an easy way to pay relayers for their work. bytes32 relayId = keccak256(abi.encodePacked(xDomainCalldata, msg.sender, block.number)); relayedMessages[relayId] = true; } /** * Replays a cross domain message to the target messenger. * @inheritdoc IL1CrossDomainMessenger */ function replayMessage( address _target, address _sender, bytes memory _message, uint256 _queueIndex, uint32 _oldGasLimit, uint32 _newGasLimit ) public override { revert("Sending via this messenger is disabled"); } /********************** * Internal Functions * **********************/ /** * Verifies that the given message is valid. * @param _xDomainCalldata Calldata to verify. * @param _proof Inclusion proof for the message. * @return Whether or not the provided message is valid. */ function _verifyXDomainMessage( bytes memory _xDomainCalldata, L2MessageInclusionProof memory _proof ) internal view returns (bool) { return (_verifyStateRootProof(_proof) && _verifyStorageProof(_xDomainCalldata, _proof)); } /** * Verifies that the state root within an inclusion proof is valid. * @param _proof Message inclusion proof. * @return Whether or not the provided proof is valid. */ function _verifyStateRootProof(L2MessageInclusionProof memory _proof) internal view returns (bool) { IStateCommitmentChain ovmStateCommitmentChain = IStateCommitmentChain( resolve("StateCommitmentChain") ); // not check time after challenge period return ( ovmStateCommitmentChain.verifyStateCommitment( _proof.stateRoot, _proof.stateRootBatchHeader, _proof.stateRootProof ) ); } /** * Verifies that the storage proof within an inclusion proof is valid. * @param _xDomainCalldata Encoded message calldata. * @param _proof Message inclusion proof. * @return Whether or not the provided proof is valid. */ function _verifyStorageProof( bytes memory _xDomainCalldata, L2MessageInclusionProof memory _proof ) internal view returns (bool) { bytes32 storageKey = keccak256( abi.encodePacked( keccak256( abi.encodePacked( _xDomainCalldata, Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER ) ), uint256(0) ) ); (bool exists, bytes memory encodedMessagePassingAccount) = Lib_SecureMerkleTrie.get( abi.encodePacked(Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER), _proof.stateTrieWitness, _proof.stateRoot ); require( exists == true, "Message passing predeploy has not been initialized or invalid proof provided." ); Lib_OVMCodec.EVMAccount memory account = Lib_OVMCodec.decodeEVMAccount( encodedMessagePassingAccount ); return Lib_SecureMerkleTrie.verifyInclusionProof( abi.encodePacked(storageKey), abi.encodePacked(uint8(1)), _proof.storageTrieWitness, account.storageRoot ); } /** * @notice Forwards multiple cross domain messages to the * L1 Cross Domain Messenger Fast for relaying * @param _messages An array of L2 to L1 messages */ function batchRelayMessages(L2ToL1Message[] calldata _messages) external onlyRelayer { for (uint256 i = 0; i < _messages.length; i++) { L2ToL1Message memory message = _messages[i]; relayMessage( message.target, message.sender, message.message, message.messageNonce, message.proof ); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.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. * * By default, the owner account will be the one that deploys the contract. 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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @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 { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing 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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @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, it is bubbled up by this * function (like regular Solidity function calls). * * 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. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @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`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // 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(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../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. * * By default, the owner account will be the one that deploys the contract. 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; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; /* Interface Imports */ import { ICrossDomainMessenger } from "../../libraries/bridge/ICrossDomainMessenger.sol"; /** * @title IL1CrossDomainMessenger */ interface IL1CrossDomainMessenger is ICrossDomainMessenger { /******************* * Data Structures * *******************/ struct L2MessageInclusionProof { bytes32 stateRoot; Lib_OVMCodec.ChainBatchHeader stateRootBatchHeader; Lib_OVMCodec.ChainInclusionProof stateRootProof; bytes stateTrieWitness; bytes storageTrieWitness; } // for batch relay struct L2ToL1Message { address target; address sender; bytes message; uint256 messageNonce; L2MessageInclusionProof proof; } /******************** * Public Functions * ********************/ /** * Relays a cross domain message to a contract. * @param _target Target contract address. * @param _sender Message sender address. * @param _message Message to send to the target. * @param _messageNonce Nonce for the provided message. * @param _proof Inclusion proof for the given message. */ function relayMessage( address _target, address _sender, bytes memory _message, uint256 _messageNonce, L2MessageInclusionProof memory _proof ) external; /** * Replays a cross domain message to the target messenger. * @param _target Target contract address. * @param _sender Original sender address. * @param _message Message to send to the target. * @param _queueIndex CTC Queue index for the message to replay. * @param _oldGasLimit Original gas limit used to send the message. * @param _newGasLimit New gas limit to be used for this message. */ function replayMessage( address _target, address _sender, bytes memory _message, uint256 _queueIndex, uint32 _oldGasLimit, uint32 _newGasLimit ) external; /** * @notice Forwards multiple cross domain messages to the L1 Cross Domain Messenger for relaying * @param _messages An array of L2 to L1 messages */ function batchRelayMessages(L2ToL1Message[] calldata _messages) external; }
// SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.9.0; /* Library Imports */ import { Lib_OVMCodec } from "../../libraries/codec/Lib_OVMCodec.sol"; /** * @title IStateCommitmentChain */ interface IStateCommitmentChain { /********** * Events * **********/ event StateBatchAppended( uint256 indexed _batchIndex, bytes32 _batchRoot, uint256 _batchSize, uint256 _prevTotalElements, bytes _extraData ); event StateBatchDeleted(uint256 indexed _batchIndex, bytes32 _batchRoot); /******************** * Public Functions * ********************/ /** * Retrieves the total number of elements submitted. * @return _totalElements Total submitted elements. */ function getTotalElements() external view returns (uint256 _totalElements); /** * Retrieves the total number of batches submitted. * @return _totalBatches Total submitted batches. */ function getTotalBatches() external view returns (uint256 _totalBatches); /** * Retrieves the timestamp of the last batch submitted by the sequencer. * @return _lastSequencerTimestamp Last sequencer batch timestamp. */ function getLastSequencerTimestamp() external view returns (uint256 _lastSequencerTimestamp); /** * Appends a batch of state roots to the chain. * @param _batch Batch of state roots. * @param _shouldStartAtElement Index of the element at which this batch should start. */ function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement) external; /** * Deletes all state roots after (and including) a given batch. * @param _batchHeader Header of the batch to start deleting from. */ function deleteStateBatch(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external; /** * Verifies a batch inclusion proof. * @param _element Hash of the element to verify a proof for. * @param _batchHeader Header of the batch in which the element was included. * @param _proof Merkle inclusion proof for the element. */ function verifyStateCommitment( bytes32 _element, Lib_OVMCodec.ChainBatchHeader memory _batchHeader, Lib_OVMCodec.ChainInclusionProof memory _proof ) external view returns (bool _verified); /** * Checks whether a given batch is still inside its fraud proof window. * @param _batchHeader Header of the batch to check. * @return _inside Whether or not the batch is inside the fraud proof window. */ function insideFraudProofWindow(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) external view returns (bool _inside); }
// SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.9.0; /** * @title ICrossDomainMessenger */ interface ICrossDomainMessenger { /********** * Events * **********/ event SentMessage( address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit ); event RelayedMessage(bytes32 indexed msgHash); event FailedRelayedMessage(bytes32 indexed msgHash); event RelayedFastMessage( address indexed target, address sender, bytes message, uint256 messageNonce ); event FailedRelayedFastMessage( address indexed target, address sender, bytes message, uint256 messageNonce ); /************* * Variables * *************/ function xDomainMessageSender() external view returns (address); /******************** * Public Functions * ********************/ /** * Sends a cross domain message to the target messenger. * @param _target Target contract address. * @param _message Message to send to the target. * @param _gasLimit Gas limit for the provided message. */ function sendMessage( address _target, bytes calldata _message, uint32 _gasLimit ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_CrossDomainUtils */ library Lib_CrossDomainUtils { /** * Generates the correct cross domain calldata for a message. * @param _target Target contract address. * @param _sender Message sender address. * @param _message Message to send to the target. * @param _messageNonce Nonce for the provided message. * @return ABI encoded cross domain calldata. */ function encodeXDomainCalldata( address _target, address _sender, bytes memory _message, uint256 _messageNonce ) internal pure returns (bytes memory) { return abi.encodeWithSignature( "relayMessage(address,address,bytes,uint256)", _target, _sender, _message, _messageNonce ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol"; import { Lib_RLPWriter } from "../rlp/Lib_RLPWriter.sol"; import { Lib_BytesUtils } from "../utils/Lib_BytesUtils.sol"; import { Lib_Bytes32Utils } from "../utils/Lib_Bytes32Utils.sol"; /** * @title Lib_OVMCodec */ library Lib_OVMCodec { /********* * Enums * *********/ enum QueueOrigin { SEQUENCER_QUEUE, L1TOL2_QUEUE } /*********** * Structs * ***********/ struct EVMAccount { uint256 nonce; uint256 balance; bytes32 storageRoot; bytes32 codeHash; } struct ChainBatchHeader { uint256 batchIndex; bytes32 batchRoot; uint256 batchSize; uint256 prevTotalElements; bytes extraData; } struct ChainInclusionProof { uint256 index; bytes32[] siblings; } struct Transaction { uint256 timestamp; uint256 blockNumber; QueueOrigin l1QueueOrigin; address l1TxOrigin; address entrypoint; uint256 gasLimit; bytes data; } struct TransactionChainElement { bool isSequenced; uint256 queueIndex; // QUEUED TX ONLY uint256 timestamp; // SEQUENCER TX ONLY uint256 blockNumber; // SEQUENCER TX ONLY bytes txData; // SEQUENCER TX ONLY } struct QueueElement { bytes32 transactionHash; uint40 timestamp; uint40 blockNumber; } /********************** * Internal Functions * **********************/ /** * Encodes a standard OVM transaction. * @param _transaction OVM transaction to encode. * @return Encoded transaction bytes. */ function encodeTransaction(Transaction memory _transaction) internal pure returns (bytes memory) { return abi.encodePacked( _transaction.timestamp, _transaction.blockNumber, _transaction.l1QueueOrigin, _transaction.l1TxOrigin, _transaction.entrypoint, _transaction.gasLimit, _transaction.data ); } /** * Hashes a standard OVM transaction. * @param _transaction OVM transaction to encode. * @return Hashed transaction */ function hashTransaction(Transaction memory _transaction) internal pure returns (bytes32) { return keccak256(encodeTransaction(_transaction)); } /** * @notice Decodes an RLP-encoded account state into a useful struct. * @param _encoded RLP-encoded account state. * @return Account state struct. */ function decodeEVMAccount(bytes memory _encoded) internal pure returns (EVMAccount memory) { Lib_RLPReader.RLPItem[] memory accountState = Lib_RLPReader.readList(_encoded); return EVMAccount({ nonce: Lib_RLPReader.readUint256(accountState[0]), balance: Lib_RLPReader.readUint256(accountState[1]), storageRoot: Lib_RLPReader.readBytes32(accountState[2]), codeHash: Lib_RLPReader.readBytes32(accountState[3]) }); } /** * Calculates a hash for a given batch header. * @param _batchHeader Header to hash. * @return Hash of the header. */ function hashBatchHeader(Lib_OVMCodec.ChainBatchHeader memory _batchHeader) internal pure returns (bytes32) { return keccak256( abi.encode( _batchHeader.batchRoot, _batchHeader.batchSize, _batchHeader.prevTotalElements, _batchHeader.extraData ) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_DefaultValues */ library Lib_DefaultValues { // The default x-domain message sender being set to a non-zero value makes // deployment a bit more expensive, but in exchange the refund on every call to // `relayMessage` by the L1 and L2 messengers will be higher. address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_PredeployAddresses */ library Lib_PredeployAddresses { address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000; address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001; address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002; address payable internal constant OVM_ETH = payable(0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000); address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007; address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008; address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009; address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010; address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011; address internal constant L2_STANDARD_TOKEN_FACTORY = 0x4200000000000000000000000000000000000012; address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* External Imports */ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title Lib_AddressManager */ contract Lib_AddressManager is Ownable { /********** * Events * **********/ event AddressSet(string indexed _name, address _newAddress, address _oldAddress); /************* * Variables * *************/ mapping(bytes32 => address) private addresses; /******************** * Public Functions * ********************/ /** * Changes the address associated with a particular name. * @param _name String name to associate an address with. * @param _address Address to associate with the name. */ function setAddress(string memory _name, address _address) external onlyOwner { bytes32 nameHash = _getNameHash(_name); address oldAddress = addresses[nameHash]; addresses[nameHash] = _address; emit AddressSet(_name, _address, oldAddress); } /** * Retrieves the address associated with a given name. * @param _name Name to retrieve an address for. * @return Address associated with the given name. */ function getAddress(string memory _name) external view returns (address) { return addresses[_getNameHash(_name)]; } /********************** * Internal Functions * **********************/ /** * Computes the hash of a name. * @param _name Name to compute a hash for. * @return Hash of the given name. */ function _getNameHash(string memory _name) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_name)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import { Lib_AddressManager } from "./Lib_AddressManager.sol"; /** * @title Lib_AddressResolver */ abstract contract Lib_AddressResolver { /************* * Variables * *************/ Lib_AddressManager public libAddressManager; /*************** * Constructor * ***************/ /** * @param _libAddressManager Address of the Lib_AddressManager. */ constructor(address _libAddressManager) { libAddressManager = Lib_AddressManager(_libAddressManager); } /******************** * Public Functions * ********************/ /** * Resolves the address associated with a given name. * @param _name Name to resolve an address for. * @return Address associated with the given name. */ function resolve(string memory _name) public view returns (address) { return libAddressManager.getAddress(_name); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_RLPReader * @dev Adapted from "RLPReader" by Hamdi Allam ([email protected]). */ library Lib_RLPReader { /************* * Constants * *************/ uint256 internal constant MAX_LIST_LENGTH = 32; /********* * Enums * *********/ enum RLPItemType { DATA_ITEM, LIST_ITEM } /*********** * Structs * ***********/ struct RLPItem { uint256 length; uint256 ptr; } /********************** * Internal Functions * **********************/ /** * Converts bytes to a reference to memory position and length. * @param _in Input bytes to convert. * @return Output memory reference. */ function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) { uint256 ptr; assembly { ptr := add(_in, 32) } return RLPItem({ length: _in.length, ptr: ptr }); } /** * Reads an RLP list value into a list of RLP items. * @param _in RLP list value. * @return Decoded RLP list items. */ function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) { (uint256 listOffset, , RLPItemType itemType) = _decodeLength(_in); require(itemType == RLPItemType.LIST_ITEM, "Invalid RLP list value."); // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by // writing to the length. Since we can't know the number of RLP items without looping over // the entire input, we'd have to loop twice to accurately size this array. It's easier to // simply set a reasonable maximum list length and decrease the size before we finish. RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH); uint256 itemCount = 0; uint256 offset = listOffset; while (offset < _in.length) { require(itemCount < MAX_LIST_LENGTH, "Provided RLP list exceeds max list length."); (uint256 itemOffset, uint256 itemLength, ) = _decodeLength( RLPItem({ length: _in.length - offset, ptr: _in.ptr + offset }) ); out[itemCount] = RLPItem({ length: itemLength + itemOffset, ptr: _in.ptr + offset }); itemCount += 1; offset += itemOffset + itemLength; } // Decrease the array size to match the actual item count. assembly { mstore(out, itemCount) } return out; } /** * Reads an RLP list value into a list of RLP items. * @param _in RLP list value. * @return Decoded RLP list items. */ function readList(bytes memory _in) internal pure returns (RLPItem[] memory) { return readList(toRLPItem(_in)); } /** * Reads an RLP bytes value into bytes. * @param _in RLP bytes value. * @return Decoded bytes. */ function readBytes(RLPItem memory _in) internal pure returns (bytes memory) { (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes value."); return _copy(_in.ptr, itemOffset, itemLength); } /** * Reads an RLP bytes value into bytes. * @param _in RLP bytes value. * @return Decoded bytes. */ function readBytes(bytes memory _in) internal pure returns (bytes memory) { return readBytes(toRLPItem(_in)); } /** * Reads an RLP string value into a string. * @param _in RLP string value. * @return Decoded string. */ function readString(RLPItem memory _in) internal pure returns (string memory) { return string(readBytes(_in)); } /** * Reads an RLP string value into a string. * @param _in RLP string value. * @return Decoded string. */ function readString(bytes memory _in) internal pure returns (string memory) { return readString(toRLPItem(_in)); } /** * Reads an RLP bytes32 value into a bytes32. * @param _in RLP bytes32 value. * @return Decoded bytes32. */ function readBytes32(RLPItem memory _in) internal pure returns (bytes32) { require(_in.length <= 33, "Invalid RLP bytes32 value."); (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes32 value."); uint256 ptr = _in.ptr + itemOffset; bytes32 out; assembly { out := mload(ptr) // Shift the bytes over to match the item size. if lt(itemLength, 32) { out := div(out, exp(256, sub(32, itemLength))) } } return out; } /** * Reads an RLP bytes32 value into a bytes32. * @param _in RLP bytes32 value. * @return Decoded bytes32. */ function readBytes32(bytes memory _in) internal pure returns (bytes32) { return readBytes32(toRLPItem(_in)); } /** * Reads an RLP uint256 value into a uint256. * @param _in RLP uint256 value. * @return Decoded uint256. */ function readUint256(RLPItem memory _in) internal pure returns (uint256) { return uint256(readBytes32(_in)); } /** * Reads an RLP uint256 value into a uint256. * @param _in RLP uint256 value. * @return Decoded uint256. */ function readUint256(bytes memory _in) internal pure returns (uint256) { return readUint256(toRLPItem(_in)); } /** * Reads an RLP bool value into a bool. * @param _in RLP bool value. * @return Decoded bool. */ function readBool(RLPItem memory _in) internal pure returns (bool) { require(_in.length == 1, "Invalid RLP boolean value."); uint256 ptr = _in.ptr; uint256 out; assembly { out := byte(0, mload(ptr)) } require(out == 0 || out == 1, "Lib_RLPReader: Invalid RLP boolean value, must be 0 or 1"); return out != 0; } /** * Reads an RLP bool value into a bool. * @param _in RLP bool value. * @return Decoded bool. */ function readBool(bytes memory _in) internal pure returns (bool) { return readBool(toRLPItem(_in)); } /** * Reads an RLP address value into a address. * @param _in RLP address value. * @return Decoded address. */ function readAddress(RLPItem memory _in) internal pure returns (address) { if (_in.length == 1) { return address(0); } require(_in.length == 21, "Invalid RLP address value."); return address(uint160(readUint256(_in))); } /** * Reads an RLP address value into a address. * @param _in RLP address value. * @return Decoded address. */ function readAddress(bytes memory _in) internal pure returns (address) { return readAddress(toRLPItem(_in)); } /** * Reads the raw bytes of an RLP item. * @param _in RLP item to read. * @return Raw RLP bytes. */ function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) { return _copy(_in); } /********************* * Private Functions * *********************/ /** * Decodes the length of an RLP item. * @param _in RLP item to decode. * @return Offset of the encoded data. * @return Length of the encoded data. * @return RLP item type (LIST_ITEM or DATA_ITEM). */ function _decodeLength(RLPItem memory _in) private pure returns ( uint256, uint256, RLPItemType ) { require(_in.length > 0, "RLP item cannot be null."); uint256 ptr = _in.ptr; uint256 prefix; assembly { prefix := byte(0, mload(ptr)) } if (prefix <= 0x7f) { // Single byte. return (0, 1, RLPItemType.DATA_ITEM); } else if (prefix <= 0xb7) { // Short string. // slither-disable-next-line variable-scope uint256 strLen = prefix - 0x80; require(_in.length > strLen, "Invalid RLP short string."); return (1, strLen, RLPItemType.DATA_ITEM); } else if (prefix <= 0xbf) { // Long string. uint256 lenOfStrLen = prefix - 0xb7; require(_in.length > lenOfStrLen, "Invalid RLP long string length."); uint256 strLen; assembly { // Pick out the string length. strLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen))) } require(_in.length > lenOfStrLen + strLen, "Invalid RLP long string."); return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM); } else if (prefix <= 0xf7) { // Short list. // slither-disable-next-line variable-scope uint256 listLen = prefix - 0xc0; require(_in.length > listLen, "Invalid RLP short list."); return (1, listLen, RLPItemType.LIST_ITEM); } else { // Long list. uint256 lenOfListLen = prefix - 0xf7; require(_in.length > lenOfListLen, "Invalid RLP long list length."); uint256 listLen; assembly { // Pick out the list length. listLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen))) } require(_in.length > lenOfListLen + listLen, "Invalid RLP long list."); return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM); } } /** * Copies the bytes from a memory location. * @param _src Pointer to the location to read from. * @param _offset Offset to start reading from. * @param _length Number of bytes to read. * @return Copied bytes. */ function _copy( uint256 _src, uint256 _offset, uint256 _length ) private pure returns (bytes memory) { bytes memory out = new bytes(_length); if (out.length == 0) { return out; } uint256 src = _src + _offset; uint256 dest; assembly { dest := add(out, 32) } // Copy over as many complete words as we can. for (uint256 i = 0; i < _length / 32; i++) { assembly { mstore(dest, mload(src)) } src += 32; dest += 32; } // Pick out the remaining bytes. uint256 mask; unchecked { mask = 256**(32 - (_length % 32)) - 1; } assembly { mstore(dest, or(and(mload(src), not(mask)), and(mload(dest), mask))) } return out; } /** * Copies an RLP item into bytes. * @param _in RLP item to copy. * @return Copied bytes. */ function _copy(RLPItem memory _in) private pure returns (bytes memory) { return _copy(_in.ptr, 0, _in.length); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_RLPWriter * @author Bakaoh (with modifications) */ library Lib_RLPWriter { /********************** * Internal Functions * **********************/ /** * RLP encodes a byte string. * @param _in The byte string to encode. * @return The RLP encoded string in bytes. */ function writeBytes(bytes memory _in) internal pure returns (bytes memory) { bytes memory encoded; if (_in.length == 1 && uint8(_in[0]) < 128) { encoded = _in; } else { encoded = abi.encodePacked(_writeLength(_in.length, 128), _in); } return encoded; } /** * RLP encodes a list of RLP encoded byte byte strings. * @param _in The list of RLP encoded byte strings. * @return The RLP encoded list of items in bytes. */ function writeList(bytes[] memory _in) internal pure returns (bytes memory) { bytes memory list = _flatten(_in); return abi.encodePacked(_writeLength(list.length, 192), list); } /** * RLP encodes a string. * @param _in The string to encode. * @return The RLP encoded string in bytes. */ function writeString(string memory _in) internal pure returns (bytes memory) { return writeBytes(bytes(_in)); } /** * RLP encodes an address. * @param _in The address to encode. * @return The RLP encoded address in bytes. */ function writeAddress(address _in) internal pure returns (bytes memory) { return writeBytes(abi.encodePacked(_in)); } /** * RLP encodes a uint. * @param _in The uint256 to encode. * @return The RLP encoded uint256 in bytes. */ function writeUint(uint256 _in) internal pure returns (bytes memory) { return writeBytes(_toBinary(_in)); } /** * RLP encodes a bool. * @param _in The bool to encode. * @return The RLP encoded bool in bytes. */ function writeBool(bool _in) internal pure returns (bytes memory) { bytes memory encoded = new bytes(1); encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80)); return encoded; } /********************* * Private Functions * *********************/ /** * Encode the first byte, followed by the `len` in binary form if `length` is more than 55. * @param _len The length of the string or the payload. * @param _offset 128 if item is string, 192 if item is list. * @return RLP encoded bytes. */ function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) { bytes memory encoded; if (_len < 56) { encoded = new bytes(1); encoded[0] = bytes1(uint8(_len) + uint8(_offset)); } else { uint256 lenLen; uint256 i = 1; while (_len / i != 0) { lenLen++; i *= 256; } encoded = new bytes(lenLen + 1); encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55); for (i = 1; i <= lenLen; i++) { encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256)); } } return encoded; } /** * Encode integer in big endian binary form with no leading zeroes. * @notice TODO: This should be optimized with assembly to save gas costs. * @param _x The integer to encode. * @return RLP encoded bytes. */ function _toBinary(uint256 _x) private pure returns (bytes memory) { bytes memory b = abi.encodePacked(_x); uint256 i = 0; for (; i < 32; i++) { if (b[i] != 0) { break; } } bytes memory res = new bytes(32 - i); for (uint256 j = 0; j < res.length; j++) { res[j] = b[i++]; } return res; } /** * Copies a piece of memory to another location. * @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol. * @param _dest Destination location. * @param _src Source location. * @param _len Length of memory to copy. */ function _memcpy( uint256 _dest, uint256 _src, uint256 _len ) private pure { uint256 dest = _dest; uint256 src = _src; uint256 len = _len; for (; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } uint256 mask; unchecked { mask = 256**(32 - len) - 1; } assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } /** * Flattens a list of byte strings into one byte string. * @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol. * @param _list List of byte strings to flatten. * @return The flattened byte string. */ function _flatten(bytes[] memory _list) private pure returns (bytes memory) { if (_list.length == 0) { return new bytes(0); } uint256 len; uint256 i = 0; for (; i < _list.length; i++) { len += _list[i].length; } bytes memory flattened = new bytes(len); uint256 flattenedPtr; assembly { flattenedPtr := add(flattened, 0x20) } for (i = 0; i < _list.length; i++) { bytes memory item = _list[i]; uint256 listPtr; assembly { listPtr := add(item, 0x20) } _memcpy(flattenedPtr, listPtr, item.length); flattenedPtr += _list[i].length; } return flattened; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import { Lib_BytesUtils } from "../utils/Lib_BytesUtils.sol"; import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol"; import { Lib_RLPWriter } from "../rlp/Lib_RLPWriter.sol"; /** * @title Lib_MerkleTrie */ library Lib_MerkleTrie { /******************* * Data Structures * *******************/ enum NodeType { BranchNode, ExtensionNode, LeafNode } struct TrieNode { bytes encoded; Lib_RLPReader.RLPItem[] decoded; } /********************** * Contract Constants * **********************/ // TREE_RADIX determines the number of elements per branch node. uint256 constant TREE_RADIX = 16; // Branch nodes have TREE_RADIX elements plus an additional `value` slot. uint256 constant BRANCH_NODE_LENGTH = TREE_RADIX + 1; // Leaf nodes and extension nodes always have two elements, a `path` and a `value`. uint256 constant LEAF_OR_EXTENSION_NODE_LENGTH = 2; // Prefixes are prepended to the `path` within a leaf or extension node and // allow us to differentiate between the two node types. `ODD` or `EVEN` is // determined by the number of nibbles within the unprefixed `path`. If the // number of nibbles if even, we need to insert an extra padding nibble so // the resulting prefixed `path` has an even number of nibbles. uint8 constant PREFIX_EXTENSION_EVEN = 0; uint8 constant PREFIX_EXTENSION_ODD = 1; uint8 constant PREFIX_LEAF_EVEN = 2; uint8 constant PREFIX_LEAF_ODD = 3; // Just a utility constant. RLP represents `NULL` as 0x80. bytes1 constant RLP_NULL = bytes1(0x80); /********************** * Internal Functions * **********************/ /** * @notice Verifies a proof that a given key/value pair is present in the * Merkle trie. * @param _key Key of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string. * @param _proof Merkle trie inclusion proof for the desired node. Unlike * traditional Merkle trees, this proof is executed top-down and consists * of a list of RLP-encoded nodes that make a path down to the target node. * @param _root Known root of the Merkle trie. Used to verify that the * included proof is correctly constructed. * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. */ function verifyInclusionProof( bytes memory _key, bytes memory _value, bytes memory _proof, bytes32 _root ) internal pure returns (bool _verified) { (bool exists, bytes memory value) = get(_key, _proof, _root); return (exists && Lib_BytesUtils.equal(_value, value)); } /** * @notice Retrieves the value associated with a given key. * @param _key Key to search for, as hex bytes. * @param _proof Merkle trie inclusion proof for the key. * @param _root Known root of the Merkle trie. * @return _exists Whether or not the key exists. * @return _value Value of the key if it exists. */ function get( bytes memory _key, bytes memory _proof, bytes32 _root ) internal pure returns (bool _exists, bytes memory _value) { TrieNode[] memory proof = _parseProof(_proof); (uint256 pathLength, bytes memory keyRemainder, bool isFinalNode) = _walkNodePath( proof, _key, _root ); bool exists = keyRemainder.length == 0; require(exists || isFinalNode, "Provided proof is invalid."); bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(""); return (exists, value); } /********************* * Private Functions * *********************/ /** * @notice Walks through a proof using a provided key. * @param _proof Inclusion proof to walk through. * @param _key Key to use for the walk. * @param _root Known root of the trie. * @return _pathLength Length of the final path * @return _keyRemainder Portion of the key remaining after the walk. * @return _isFinalNode Whether or not we've hit a dead end. */ function _walkNodePath( TrieNode[] memory _proof, bytes memory _key, bytes32 _root ) private pure returns ( uint256 _pathLength, bytes memory _keyRemainder, bool _isFinalNode ) { uint256 pathLength = 0; bytes memory key = Lib_BytesUtils.toNibbles(_key); bytes32 currentNodeID = _root; uint256 currentKeyIndex = 0; uint256 currentKeyIncrement = 0; TrieNode memory currentNode; // Proof is top-down, so we start at the first element (root). for (uint256 i = 0; i < _proof.length; i++) { currentNode = _proof[i]; currentKeyIndex += currentKeyIncrement; // Keep track of the proof elements we actually need. // It's expensive to resize arrays, so this simply reduces gas costs. pathLength += 1; if (currentKeyIndex == 0) { // First proof element is always the root node. require(keccak256(currentNode.encoded) == currentNodeID, "Invalid root hash"); } else if (currentNode.encoded.length >= 32) { // Nodes 32 bytes or larger are hashed inside branch nodes. require( keccak256(currentNode.encoded) == currentNodeID, "Invalid large internal hash" ); } else { // Nodes smaller than 31 bytes aren't hashed. require( Lib_BytesUtils.toBytes32(currentNode.encoded) == currentNodeID, "Invalid internal node hash" ); } if (currentNode.decoded.length == BRANCH_NODE_LENGTH) { if (currentKeyIndex == key.length) { // We've hit the end of the key // meaning the value should be within this branch node. break; } else { // We're not at the end of the key yet. // Figure out what the next node ID should be and continue. uint8 branchKey = uint8(key[currentKeyIndex]); Lib_RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey]; currentNodeID = _getNodeID(nextNode); currentKeyIncrement = 1; continue; } } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) { bytes memory path = _getNodePath(currentNode); uint8 prefix = uint8(path[0]); uint8 offset = 2 - (prefix % 2); bytes memory pathRemainder = Lib_BytesUtils.slice(path, offset); bytes memory keyRemainder = Lib_BytesUtils.slice(key, currentKeyIndex); uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder); if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) { if ( pathRemainder.length == sharedNibbleLength && keyRemainder.length == sharedNibbleLength ) { // The key within this leaf matches our key exactly. // Increment the key index to reflect that we have no remainder. currentKeyIndex += sharedNibbleLength; } // We've hit a leaf node, so our next node should be NULL. currentNodeID = bytes32(RLP_NULL); break; } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) { if (sharedNibbleLength != pathRemainder.length) { // Our extension node is not identical to the remainder. // We've hit the end of this path // updates will need to modify this extension. currentNodeID = bytes32(RLP_NULL); break; } else { // Our extension shares some nibbles. // Carry on to the next node. currentNodeID = _getNodeID(currentNode.decoded[1]); currentKeyIncrement = sharedNibbleLength; continue; } } else { revert("Received a node with an unknown prefix"); } } else { revert("Received an unparseable node."); } } // If our node ID is NULL, then we're at a dead end. bool isFinalNode = currentNodeID == bytes32(RLP_NULL); return (pathLength, Lib_BytesUtils.slice(key, currentKeyIndex), isFinalNode); } /** * @notice Parses an RLP-encoded proof into something more useful. * @param _proof RLP-encoded proof to parse. * @return _parsed Proof parsed into easily accessible structs. */ function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) { Lib_RLPReader.RLPItem[] memory nodes = Lib_RLPReader.readList(_proof); TrieNode[] memory proof = new TrieNode[](nodes.length); for (uint256 i = 0; i < nodes.length; i++) { bytes memory encoded = Lib_RLPReader.readBytes(nodes[i]); proof[i] = TrieNode({ encoded: encoded, decoded: Lib_RLPReader.readList(encoded) }); } return proof; } /** * @notice Picks out the ID for a node. Node ID is referred to as the * "hash" within the specification, but nodes < 32 bytes are not actually * hashed. * @param _node Node to pull an ID for. * @return _nodeID ID for the node, depending on the size of its contents. */ function _getNodeID(Lib_RLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) { bytes memory nodeID; if (_node.length < 32) { // Nodes smaller than 32 bytes are RLP encoded. nodeID = Lib_RLPReader.readRawBytes(_node); } else { // Nodes 32 bytes or larger are hashed. nodeID = Lib_RLPReader.readBytes(_node); } return Lib_BytesUtils.toBytes32(nodeID); } /** * @notice Gets the path for a leaf or extension node. * @param _node Node to get a path for. * @return _path Node path, converted to an array of nibbles. */ function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) { return Lib_BytesUtils.toNibbles(Lib_RLPReader.readBytes(_node.decoded[0])); } /** * @notice Gets the path for a node. * @param _node Node to get a value for. * @return _value Node value, as hex bytes. */ function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) { return Lib_RLPReader.readBytes(_node.decoded[_node.decoded.length - 1]); } /** * @notice Utility; determines the number of nibbles shared between two * nibble arrays. * @param _a First nibble array. * @param _b Second nibble array. * @return _shared Number of shared nibbles. */ function _getSharedNibbleLength(bytes memory _a, bytes memory _b) private pure returns (uint256 _shared) { uint256 i = 0; while (_a.length > i && _b.length > i && _a[i] == _b[i]) { i++; } return i; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import { Lib_MerkleTrie } from "./Lib_MerkleTrie.sol"; /** * @title Lib_SecureMerkleTrie */ library Lib_SecureMerkleTrie { /********************** * Internal Functions * **********************/ /** * @notice Verifies a proof that a given key/value pair is present in the * Merkle trie. * @param _key Key of the node to search for, as a hex string. * @param _value Value of the node to search for, as a hex string. * @param _proof Merkle trie inclusion proof for the desired node. Unlike * traditional Merkle trees, this proof is executed top-down and consists * of a list of RLP-encoded nodes that make a path down to the target node. * @param _root Known root of the Merkle trie. Used to verify that the * included proof is correctly constructed. * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. */ function verifyInclusionProof( bytes memory _key, bytes memory _value, bytes memory _proof, bytes32 _root ) internal pure returns (bool _verified) { bytes memory key = _getSecureKey(_key); return Lib_MerkleTrie.verifyInclusionProof(key, _value, _proof, _root); } /** * @notice Retrieves the value associated with a given key. * @param _key Key to search for, as hex bytes. * @param _proof Merkle trie inclusion proof for the key. * @param _root Known root of the Merkle trie. * @return _exists Whether or not the key exists. * @return _value Value of the key if it exists. */ function get( bytes memory _key, bytes memory _proof, bytes32 _root ) internal pure returns (bool _exists, bytes memory _value) { bytes memory key = _getSecureKey(_key); return Lib_MerkleTrie.get(key, _proof, _root); } /********************* * Private Functions * *********************/ /** * Computes the secure counterpart to a key. * @param _key Key to get a secure key from. * @return _secureKey Secure version of the key. */ function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) { return abi.encodePacked(keccak256(_key)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_Byte32Utils */ library Lib_Bytes32Utils { /********************** * Internal Functions * **********************/ /** * Converts a bytes32 value to a boolean. Anything non-zero will be converted to "true." * @param _in Input bytes32 value. * @return Bytes32 as a boolean. */ function toBool(bytes32 _in) internal pure returns (bool) { return _in != 0; } /** * Converts a boolean to a bytes32 value. * @param _in Input boolean value. * @return Boolean as a bytes32. */ function fromBool(bool _in) internal pure returns (bytes32) { return bytes32(uint256(_in ? 1 : 0)); } /** * Converts a bytes32 value to an address. Takes the *last* 20 bytes. * @param _in Input bytes32 value. * @return Bytes32 as an address. */ function toAddress(bytes32 _in) internal pure returns (address) { return address(uint160(uint256(_in))); } /** * Converts an address to a bytes32. * @param _in Input address value. * @return Address as a bytes32. */ function fromAddress(address _in) internal pure returns (bytes32) { return bytes32(uint256(uint160(_in))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /** * @title Lib_BytesUtils */ library Lib_BytesUtils { /********************** * Internal Functions * **********************/ function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_start + _length >= _start, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) { if (_start >= _bytes.length) { return bytes(""); } return slice(_bytes, _start, _bytes.length - _start); } function toBytes32(bytes memory _bytes) internal pure returns (bytes32) { if (_bytes.length < 32) { bytes32 ret; assembly { ret := mload(add(_bytes, 32)) } return ret; } return abi.decode(_bytes, (bytes32)); // will truncate if input length > 32 bytes } function toUint256(bytes memory _bytes) internal pure returns (uint256) { return uint256(toBytes32(_bytes)); } function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) { bytes memory nibbles = new bytes(_bytes.length * 2); for (uint256 i = 0; i < _bytes.length; i++) { nibbles[i * 2] = _bytes[i] >> 4; nibbles[i * 2 + 1] = bytes1(uint8(_bytes[i]) % 16); } return nibbles; } function fromNibbles(bytes memory _bytes) internal pure returns (bytes memory) { bytes memory ret = new bytes(_bytes.length / 2); for (uint256 i = 0; i < ret.length; i++) { ret[i] = (_bytes[i * 2] << 4) | (_bytes[i * 2 + 1]); } return ret; } function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) { return keccak256(_bytes) == keccak256(_other); } }
{ "optimizer": { "enabled": true, "runs": 10000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"messageNonce","type":"uint256"}],"name":"FailedRelayedFastMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"}],"name":"FailedRelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_xDomainCalldataHash","type":"bytes32"}],"name":"MessageAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"_xDomainCalldataHash","type":"bytes32"}],"name":"MessageBlocked","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"messageNonce","type":"uint256"}],"name":"RelayedFastMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"msgHash","type":"bytes32"}],"name":"RelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes","name":"message","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"messageNonce","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasLimit","type":"uint256"}],"name":"SentMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_xDomainCalldataHash","type":"bytes32"}],"name":"allowMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes","name":"message","type":"bytes"},{"internalType":"uint256","name":"messageNonce","type":"uint256"},{"components":[{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"components":[{"internalType":"uint256","name":"batchIndex","type":"uint256"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"},{"internalType":"uint256","name":"batchSize","type":"uint256"},{"internalType":"uint256","name":"prevTotalElements","type":"uint256"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct Lib_OVMCodec.ChainBatchHeader","name":"stateRootBatchHeader","type":"tuple"},{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"}],"internalType":"struct Lib_OVMCodec.ChainInclusionProof","name":"stateRootProof","type":"tuple"},{"internalType":"bytes","name":"stateTrieWitness","type":"bytes"},{"internalType":"bytes","name":"storageTrieWitness","type":"bytes"}],"internalType":"struct IL1CrossDomainMessenger.L2MessageInclusionProof","name":"proof","type":"tuple"}],"internalType":"struct IL1CrossDomainMessenger.L2ToL1Message[]","name":"_messages","type":"tuple[]"}],"name":"batchRelayMessages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_xDomainCalldataHash","type":"bytes32"}],"name":"blockMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"blockedMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"failedMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_libAddressManager","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"libAddressManager","outputs":[{"internalType":"contract Lib_AddressManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint256","name":"_messageNonce","type":"uint256"},{"components":[{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"components":[{"internalType":"uint256","name":"batchIndex","type":"uint256"},{"internalType":"bytes32","name":"batchRoot","type":"bytes32"},{"internalType":"uint256","name":"batchSize","type":"uint256"},{"internalType":"uint256","name":"prevTotalElements","type":"uint256"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct Lib_OVMCodec.ChainBatchHeader","name":"stateRootBatchHeader","type":"tuple"},{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"}],"internalType":"struct Lib_OVMCodec.ChainInclusionProof","name":"stateRootProof","type":"tuple"},{"internalType":"bytes","name":"stateTrieWitness","type":"bytes"},{"internalType":"bytes","name":"storageTrieWitness","type":"bytes"}],"internalType":"struct IL1CrossDomainMessenger.L2MessageInclusionProof","name":"_proof","type":"tuple"}],"name":"relayMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"relayedMessages","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint256","name":"_queueIndex","type":"uint256"},{"internalType":"uint32","name":"_oldGasLimit","type":"uint32"},{"internalType":"uint32","name":"_newGasLimit","type":"uint32"}],"name":"replayMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"}],"name":"resolve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_target","type":"address"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"uint32","name":"_gasLimit","type":"uint32"}],"name":"sendMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"successfulMessages","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":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"xDomainMessageSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405260cd80546001600160a01b03191661dead17905534801561002457600080fd5b50600080546001600160a01b031916905561373d806100446000396000f3fe608060405234801561001057600080fd5b506004361061016c5760003560e01c8063715018a6116100cd578063b1b1b20911610081578063c6b94ab011610066578063c6b94ab0146102ff578063d7fd19dd14610322578063f2fde38b1461033557600080fd5b8063b1b1b209146102c9578063c4d66de8146102ec57600080fd5b80638456cb59116100b25780638456cb59146102805780638da5cb5b14610288578063a4e7f8bd146102a657600080fd5b8063715018a61461026557806381ada46c1461026d57600080fd5b80633f4ba83a116101245780635c975abb116101095780635c975abb146102445780636e296e451461024f5780636f1c8d471461025757600080fd5b80633f4ba83a14610229578063461a44781461023157600080fd5b806321d800ec1161015557806321d800ec14610199578063299ca478146101d15780633dbb202b1461021657600080fd5b80630ecf2eea1461017157806316e9cd9b14610186575b600080fd5b61018461017f366004612c18565b610348565b005b610184610194366004612c31565b610393565b6101bc6101a7366004612c18565b60ca6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6000546101f19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c8565b610184610224366004612e05565b610511565b61018461057f565b6101f161023f366004612e65565b610591565b60655460ff166101bc565b6101f161063e565b610184610224366004612eb6565b6101846106c8565b61018461027b366004612c18565b6106da565b610184610722565b60335473ffffffffffffffffffffffffffffffffffffffff166101f1565b6101bc6102b4366004612c18565b60cc6020526000908152604090205460ff1681565b6101bc6102d7366004612c18565b60cb6020526000908152604090205460ff1681565b6101846102fa366004612f42565b610732565b6101bc61030d366004612c18565b60c96020526000908152604090205460ff1681565b610184610330366004613142565b610a0a565b610184610343366004612f42565b610eee565b610350610f8b565b600081815260c96020526040808220805460ff191660011790555182917ff52508d5339edf0d7e5060a416df98db067af561bdc60872d29c0439eaa13a0291a250565b6103d16040518060400160405280600f81526020017f4f564d5f4661737452656c617965720000000000000000000000000000000000815250610591565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461049c5760405162461bcd60e51b815260206004820152604a60248201527f4c3143726f7373446f6d61696e4d657373656e676572466173743a2046756e6360448201527f74696f6e2063616e206f6e6c792062652063616c6c656420627920746865204660648201527f61737452656c6179657200000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b60005b8181101561050c5760008383838181106104bb576104bb6131d5565b90506020028101906104cd9190613204565b6104d690613242565b90506104f981600001518260200151836040015184606001518560800151610a0a565b508061050481613302565b91505061049f565b505050565b60405162461bcd60e51b815260206004820152602660248201527f53656e64696e67207669612074686973206d657373656e67657220697320646960448201527f7361626c656400000000000000000000000000000000000000000000000000006064820152608401610493565b610587610f8b565b61058f610ff2565b565b600080546040517fbf40fac100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac1906105e8908590600401613397565b60206040518083038186803b15801561060057600080fd5b505afa158015610614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063891906133aa565b92915050565b60cd5460009073ffffffffffffffffffffffffffffffffffffffff1661dead14156106ab5760405162461bcd60e51b815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f7420736574006044820152606401610493565b5060cd5473ffffffffffffffffffffffffffffffffffffffff1690565b6106d0610f8b565b61058f6000611051565b6106e2610f8b565b600081815260c96020526040808220805460ff191690555182917f52c8a2680a9f4cc0ad0bf88f32096eadbebf0646ea611d93a0ce6a29a024040591a250565b61072a610f8b565b61058f6110c8565b6000547501000000000000000000000000000000000000000000900460ff161580801561077d575060005460017401000000000000000000000000000000000000000090910460ff16105b806107af5750303b1580156107af575060005474010000000000000000000000000000000000000000900460ff166001145b6108215760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610493565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905580156108a757600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60005473ffffffffffffffffffffffffffffffffffffffff16156109335760405162461bcd60e51b815260206004820152602a60248201527f4c3143726f7373446f6d61696e4d657373656e67657220616c7265616479206960448201527f6e7469616c697a65642e000000000000000000000000000000000000000000006064820152608401610493565b6000805473ffffffffffffffffffffffffffffffffffffffff84167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560cd805490911661dead17905561098b611105565b610993611196565b61099b611230565b6109a36112cd565b8015610a0657600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60026097541415610a5d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610493565b6002609755610a6a611365565b6000610a78868686866113b8565b9050610a848183611433565b1515600114610afb5760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f7420626520766560448201527f7269666965642e000000000000000000000000000000000000000000000000006064820152608401610493565b8051602080830191909120600081815260cb90925260409091205460ff1615610b8c5760405162461bcd60e51b815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201527f6e2072656365697665642e0000000000000000000000000000000000000000006064820152608401610493565b600081815260c9602052604090205460ff1615610c115760405162461bcd60e51b815260206004820152602260248201527f50726f7669646564206d65737361676520686173206265656e20626c6f636b6560448201527f642e0000000000000000000000000000000000000000000000000000000000006064820152608401610493565b610c4f6040518060400160405280601981526020017f43616e6f6e6963616c5472616e73616374696f6e436861696e00000000000000815250610591565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415610cf05760405162461bcd60e51b815260206004820152603360248201527f43616e6e6f742073656e64204c322d3e4c31206d6573736167657320746f204c60448201527f312073797374656d20636f6e7472616374732e000000000000000000000000006064820152608401610493565b60cd80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88811691909117909155604051600091891690610d499088906133c7565b6000604051808303816000865af19150503d8060008114610d86576040519150601f19603f3d011682016040523d82523d6000602084013e610d8b565b606091505b505060cd80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560011415610e3857600082815260cb602052604090819020805460ff191660011790555173ffffffffffffffffffffffffffffffffffffffff8916907f6166323e9134edd95d3f747dcf3212a095e2916dcfa483d348bcc3716f7f2cfb90610e2b908a908a908a906133d9565b60405180910390a2610e97565b600082905260cc60205260405173ffffffffffffffffffffffffffffffffffffffff8916907fc6ac8f8e058accca572db6f130cf8f9186f28f95658153e1fd8135d094add97590610e8e908a908a908a906133d9565b60405180910390a25b6000833343604051602001610eae93929190613418565b60408051601f198184030181529181528151602092830120600090815260ca9092529020805460ff19166001908117909155609755505050505050505050565b610ef6610f8b565b73ffffffffffffffffffffffffffffffffffffffff8116610f7f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610493565b610f8881611051565b50565b60335473ffffffffffffffffffffffffffffffffffffffff16331461058f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610493565b610ffa611456565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6110d0611365565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586110273390565b6000547501000000000000000000000000000000000000000000900460ff1661058f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b6000547501000000000000000000000000000000000000000000900460ff166112275760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b61058f33611051565b6000547501000000000000000000000000000000000000000000900460ff166112c15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b6065805460ff19169055565b6000547501000000000000000000000000000000000000000000900460ff1661135e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b6001609755565b60655460ff161561058f5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610493565b6060848484846040516024016113d1949392919061346a565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b600061143e826114a8565b801561144f575061144f838361159c565b9392505050565b60655460ff1661058f5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610493565b6000806114e96040518060400160405280601481526020017f5374617465436f6d6d69746d656e74436861696e000000000000000000000000815250610591565b8351602085015160408087015190517f4d69ee5700000000000000000000000000000000000000000000000000000000815293945073ffffffffffffffffffffffffffffffffffffffff851693634d69ee579361154c93909290916004016134b4565b60206040518083038186803b15801561156457600080fd5b505afa158015611578573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144f919061355f565b600080837342000000000000000000000000000000000000076040516020016115c6929190613581565b60408051601f1981840301815282825280516020918201209083015260009082015260600160408051601f198184030181529082905280516020918201207f420000000000000000000000000000000000000000000000000000000000000091830191909152915060009081906116569060340160408051601f1981840301815291905260608701518751611780565b90925090506001821515146116f95760405162461bcd60e51b815260206004820152604d60248201527f4d6573736167652070617373696e67207072656465706c6f7920686173206e6f60448201527f74206265656e20696e697469616c697a6564206f7220696e76616c696420707260648201527f6f6f662070726f76696465642e00000000000000000000000000000000000000608482015260a401610493565b6000611704826117a9565b90506117758460405160200161171c91815260200190565b60408051601f19818403018152908290527f01000000000000000000000000000000000000000000000000000000000000006020830152906021016040516020818303038152906040528860800151846040015161186d565b979650505050505050565b60006060600061178f86611891565b905061179c8186866118c3565b9250925050935093915050565b6040805160808101825260008082526020820181905291810182905260608101829052906117d68361199e565b90506040518060800160405280611806836000815181106117f9576117f96131d5565b60200260200101516119d1565b8152602001611821836001815181106117f9576117f96131d5565b81526020016118498360028151811061183c5761183c6131d5565b60200260200101516119d8565b81526020016118648360038151811061183c5761183c6131d5565b90529392505050565b60008061187986611891565b905061188781868686611ada565b9695505050505050565b606081805190602001206040516020016118ad91815260200190565b6040516020818303038152906040529050919050565b6000606060006118d285611b10565b905060008060006118e4848a89611c0b565b815192955090935091501580806118f85750815b6119445760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610493565b600081611960576040518060200160405280600081525061198c565b61198c8661196f6001886135cb565b8151811061197f5761197f6131d5565b60200260200101516120a6565b919b919a509098505050505050505050565b604080518082018252600080825260209182015281518083019092528251825280830190820152606090610638906120d0565b6000610638825b6000602182600001511115611a2f5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610493565b6000806000611a3d856122cf565b919450925090506000816001811115611a5857611a586135e2565b14611aa55760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610493565b6000838660200151611ab79190613611565b805190915060208410156118875760208490036101000a90049695505050505050565b6000806000611aea8786866118c3565b915091508180156117755750805160208083019190912087519188019190912014611775565b60606000611b1d8361199e565b90506000815167ffffffffffffffff811115611b3b57611b3b612cc8565b604051908082528060200260200182016040528015611b8057816020015b6040805180820190915260608082526020820152815260200190600190039081611b595790505b50905060005b8251811015611c03576000611bb3848381518110611ba657611ba66131d5565b6020026020010151612620565b90506040518060400160405280828152602001611bcf8361199e565b815250838381518110611be457611be46131d5565b6020026020010181905250508080611bfb90613302565b915050611b86565b509392505050565b60006060818080611c1b876126b0565b90506000869050600080611c42604051806040016040528060608152602001606081525090565b60005b8c51811015612062578c8181518110611c6057611c606131d5565b602002602001015191508284611c769190613611565b9350611c83600188613611565b965083611ce757815180516020909101208514611ce25760405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610493565b611da4565b815151602011611d4957815180516020909101208514611ce25760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610493565b84611d578360000151612833565b14611da45760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610493565b611db060106001613611565b8260200151511415611e29578551841415611dca57612062565b6000868581518110611dde57611dde6131d5565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110611e0957611e096131d5565b60200260200101519050611e1c8161285b565b9650600194505050612050565b60028260200151511415612008576000611e4283612891565b9050600081600081518110611e5957611e596131d5565b016020015160f81c90506000611e70600283613658565b611e7b90600261367a565b90506000611e8c848360ff166128b5565b90506000611e9a8b8a6128b5565b90506000611ea883836128eb565b905060ff851660021480611ebf575060ff85166003145b15611f1557808351148015611ed45750808251145b15611ee657611ee3818b613611565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950612062945050505050565b60ff85161580611f28575060ff85166001145b15611f9a5782518114611f6457507f80000000000000000000000000000000000000000000000000000000000000009950612062945050505050565b611f8b8860200151600181518110611f7e57611f7e6131d5565b602002602001015161285b565b9a509750612050945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610493565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610493565b8061205a81613302565b915050611c45565b507f800000000000000000000000000000000000000000000000000000000000000084148661209187866128b5565b909e909d50909b509950505050505050505050565b60208101518051606091610638916120c0906001906135cb565b81518110611ba657611ba66131d5565b60606000806120de846122cf565b919350909150600190508160018111156120fa576120fa6135e2565b146121475760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610493565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816121605790505090506000835b86518110156122c4576020821061220c5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610493565b6000806122496040518060400160405280858c6000015161222d91906135cb565b8152602001858c602001516122429190613611565b90526122cf565b5091509150604051806040016040528083836122659190613611565b8152602001848b6020015161227a9190613611565b81525085858151811061228f5761228f6131d5565b60209081029190910101526122a5600185613611565b93506122b18183613611565b6122bb9084613611565b9250505061218d565b508152949350505050565b6000806000808460000151116123275760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610493565b6020840151805160001a607f811161234c576000600160009450945094505050612619565b60b781116123c85760006123616080836135cb565b9050808760000151116123b65760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610493565b60019550935060009250612619915050565b60bf81116124b75760006123dd60b7836135cb565b9050808760000151116124325760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610493565b600183015160208290036101000a900461244c8183613611565b88511161249b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610493565b6124a6826001613611565b965094506000935061261992505050565b60f781116125325760006124cc60c0836135cb565b9050808760000151116125215760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610493565b600195509350849250612619915050565b600061253f60f7836135cb565b9050808760000151116125945760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610493565b600183015160208290036101000a90046125ae8183613611565b8851116125fd5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610493565b612608826001613611565b965094506001935061261992505050565b9193909250565b60606000806000612630856122cf565b91945092509050600081600181111561264b5761264b6135e2565b146126985760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610493565b6126a785602001518484612997565b95945050505050565b60606000825160026126c2919061369d565b67ffffffffffffffff8111156126da576126da612cc8565b6040519080825280601f01601f191660200182016040528015612704576020820181803683370190505b50905060005b835181101561282c576004848281518110612727576127276131d5565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261275c83600261369d565b8151811061276c5761276c6131d5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106127af576127af6131d5565b01602001516127c1919060f81c613658565b60f81b826127d083600261369d565b6127db906001613611565b815181106127eb576127eb6131d5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061282481613302565b91505061270a565b5092915050565b600060208251101561284757506020015190565b8180602001905181019061063891906136da565b6000606060208360000151101561287c5761287583612a76565b9050612888565b61288583612620565b90505b61144f81612833565b60606106386128b08360200151600081518110611ba657611ba66131d5565b6126b0565b6060825182106128d45750604080516020810190915260008152610638565b61144f83838486516128e691906135cb565b612a81565b6000805b8084511180156128ff5750808351115b80156129805750828181518110612918576129186131d5565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848281518110612957576129576131d5565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561144f578061298f81613302565b9150506128ef565b606060008267ffffffffffffffff8111156129b4576129b4612cc8565b6040519080825280601f01601f1916602001820160405280156129de576020820181803683370190505b5090508051600014156129f257905061144f565b60006129fe8587613611565b90506020820160005b612a126020876136f3565b811015612a495782518252612a28602084613611565b9250612a35602083613611565b915080612a4181613302565b915050612a07565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061063882612c02565b606081612a8f81601f613611565b1015612add5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610493565b82612ae88382613611565b1015612b365760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610493565b612b408284613611565b84511015612b905760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610493565b606082158015612baf5760405191506000825260208201604052612bf9565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612be8578051835260209283019201612bd0565b5050858452601f01601f1916604052505b50949350505050565b6060610638826020015160008460000151612997565b600060208284031215612c2a57600080fd5b5035919050565b60008060208385031215612c4457600080fd5b823567ffffffffffffffff80821115612c5c57600080fd5b818501915085601f830112612c7057600080fd5b813581811115612c7f57600080fd5b8660208260051b8501011115612c9457600080fd5b60209290920196919550909350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f8857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612d1a57612d1a612cc8565b60405290565b6040805190810167ffffffffffffffff81118282101715612d1a57612d1a612cc8565b604051601f8201601f1916810167ffffffffffffffff81118282101715612d6c57612d6c612cc8565b604052919050565b600067ffffffffffffffff831115612d8e57612d8e612cc8565b612da16020601f19601f86011601612d43565b9050828152838383011115612db557600080fd5b828260208301376000602084830101529392505050565b600082601f830112612ddd57600080fd5b61144f83833560208501612d74565b803563ffffffff81168114612e0057600080fd5b919050565b600080600060608486031215612e1a57600080fd5b8335612e2581612ca6565b9250602084013567ffffffffffffffff811115612e4157600080fd5b612e4d86828701612dcc565b925050612e5c60408501612dec565b90509250925092565b600060208284031215612e7757600080fd5b813567ffffffffffffffff811115612e8e57600080fd5b8201601f81018413612e9f57600080fd5b612eae84823560208401612d74565b949350505050565b60008060008060008060c08789031215612ecf57600080fd5b8635612eda81612ca6565b95506020870135612eea81612ca6565b9450604087013567ffffffffffffffff811115612f0657600080fd5b612f1289828a01612dcc565b94505060608701359250612f2860808801612dec565b9150612f3660a08801612dec565b90509295509295509295565b600060208284031215612f5457600080fd5b813561144f81612ca6565b600060a08284031215612f7157600080fd5b612f79612cf7565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff811115612fb757600080fd5b612fc384828501612dcc565b60808301525092915050565b600060408284031215612fe157600080fd5b612fe9612d20565b90508135815260208083013567ffffffffffffffff8082111561300b57600080fd5b818501915085601f83011261301f57600080fd5b81358181111561303157613031612cc8565b8060051b9150613042848301612d43565b818152918301840191848101908884111561305c57600080fd5b938501935b8385101561307a57843582529385019390850190613061565b808688015250505050505092915050565b600060a0828403121561309d57600080fd5b6130a5612cf7565b905081358152602082013567ffffffffffffffff808211156130c657600080fd5b6130d285838601612f5f565b602084015260408401359150808211156130eb57600080fd5b6130f785838601612fcf565b6040840152606084013591508082111561311057600080fd5b61311c85838601612dcc565b6060840152608084013591508082111561313557600080fd5b50612fc384828501612dcc565b600080600080600060a0868803121561315a57600080fd5b853561316581612ca6565b9450602086013561317581612ca6565b9350604086013567ffffffffffffffff8082111561319257600080fd5b61319e89838a01612dcc565b94506060880135935060808801359150808211156131bb57600080fd5b506131c88882890161308b565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261323857600080fd5b9190910192915050565b600060a0823603121561325457600080fd5b61325c612cf7565b823561326781612ca6565b8152602083013561327781612ca6565b6020820152604083013567ffffffffffffffff8082111561329757600080fd5b6132a336838701612dcc565b60408401526060850135606084015260808501359150808211156132c657600080fd5b50612fc33682860161308b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613334576133346132d3565b5060010190565b60005b8381101561335657818101518382015260200161333e565b83811115613365576000848401525b50505050565b6000815180845261338381602086016020860161333b565b601f01601f19169290920160200192915050565b60208152600061144f602083018461336b565b6000602082840312156133bc57600080fd5b815161144f81612ca6565b6000825161323881846020870161333b565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000613408606083018561336b565b9050826040830152949350505050565b6000845161342a81846020890161333b565b60609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001691909301908152601481019190915260340192915050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250608060408301526134a3608083018561336b565b905082606083015295945050505050565b8381526000602060608184015284516060840152808501516080840152604085015160a0840152606085015160c0840152608085015160a060e08501526134ff61010085018261336b565b905083810360408501526040810185518252828601516040848401528181518084526060850191508583019450600093505b808410156135515784518252938501936001939093019290850190613531565b509998505050505050505050565b60006020828403121561357157600080fd5b8151801515811461144f57600080fd5b6000835161359381846020880161333b565b60609390931b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190920190815260140192915050565b6000828210156135dd576135dd6132d3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008219821115613624576136246132d3565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061366b5761366b613629565b8060ff84160691505092915050565b600060ff821660ff841680821015613694576136946132d3565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156136d5576136d56132d3565b500290565b6000602082840312156136ec57600080fd5b5051919050565b60008261370257613702613629565b50049056fea26469706673582212202de197a29c4cdce4170574fe7ddb3adcfb6375d36dc28b79414f33371d02f4c364736f6c63430008090033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061016c5760003560e01c8063715018a6116100cd578063b1b1b20911610081578063c6b94ab011610066578063c6b94ab0146102ff578063d7fd19dd14610322578063f2fde38b1461033557600080fd5b8063b1b1b209146102c9578063c4d66de8146102ec57600080fd5b80638456cb59116100b25780638456cb59146102805780638da5cb5b14610288578063a4e7f8bd146102a657600080fd5b8063715018a61461026557806381ada46c1461026d57600080fd5b80633f4ba83a116101245780635c975abb116101095780635c975abb146102445780636e296e451461024f5780636f1c8d471461025757600080fd5b80633f4ba83a14610229578063461a44781461023157600080fd5b806321d800ec1161015557806321d800ec14610199578063299ca478146101d15780633dbb202b1461021657600080fd5b80630ecf2eea1461017157806316e9cd9b14610186575b600080fd5b61018461017f366004612c18565b610348565b005b610184610194366004612c31565b610393565b6101bc6101a7366004612c18565b60ca6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6000546101f19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101c8565b610184610224366004612e05565b610511565b61018461057f565b6101f161023f366004612e65565b610591565b60655460ff166101bc565b6101f161063e565b610184610224366004612eb6565b6101846106c8565b61018461027b366004612c18565b6106da565b610184610722565b60335473ffffffffffffffffffffffffffffffffffffffff166101f1565b6101bc6102b4366004612c18565b60cc6020526000908152604090205460ff1681565b6101bc6102d7366004612c18565b60cb6020526000908152604090205460ff1681565b6101846102fa366004612f42565b610732565b6101bc61030d366004612c18565b60c96020526000908152604090205460ff1681565b610184610330366004613142565b610a0a565b610184610343366004612f42565b610eee565b610350610f8b565b600081815260c96020526040808220805460ff191660011790555182917ff52508d5339edf0d7e5060a416df98db067af561bdc60872d29c0439eaa13a0291a250565b6103d16040518060400160405280600f81526020017f4f564d5f4661737452656c617965720000000000000000000000000000000000815250610591565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461049c5760405162461bcd60e51b815260206004820152604a60248201527f4c3143726f7373446f6d61696e4d657373656e676572466173743a2046756e6360448201527f74696f6e2063616e206f6e6c792062652063616c6c656420627920746865204660648201527f61737452656c6179657200000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b60005b8181101561050c5760008383838181106104bb576104bb6131d5565b90506020028101906104cd9190613204565b6104d690613242565b90506104f981600001518260200151836040015184606001518560800151610a0a565b508061050481613302565b91505061049f565b505050565b60405162461bcd60e51b815260206004820152602660248201527f53656e64696e67207669612074686973206d657373656e67657220697320646960448201527f7361626c656400000000000000000000000000000000000000000000000000006064820152608401610493565b610587610f8b565b61058f610ff2565b565b600080546040517fbf40fac100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063bf40fac1906105e8908590600401613397565b60206040518083038186803b15801561060057600080fd5b505afa158015610614573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063891906133aa565b92915050565b60cd5460009073ffffffffffffffffffffffffffffffffffffffff1661dead14156106ab5760405162461bcd60e51b815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f7420736574006044820152606401610493565b5060cd5473ffffffffffffffffffffffffffffffffffffffff1690565b6106d0610f8b565b61058f6000611051565b6106e2610f8b565b600081815260c96020526040808220805460ff191690555182917f52c8a2680a9f4cc0ad0bf88f32096eadbebf0646ea611d93a0ce6a29a024040591a250565b61072a610f8b565b61058f6110c8565b6000547501000000000000000000000000000000000000000000900460ff161580801561077d575060005460017401000000000000000000000000000000000000000090910460ff16105b806107af5750303b1580156107af575060005474010000000000000000000000000000000000000000900460ff166001145b6108215760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610493565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905580156108a757600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790555b60005473ffffffffffffffffffffffffffffffffffffffff16156109335760405162461bcd60e51b815260206004820152602a60248201527f4c3143726f7373446f6d61696e4d657373656e67657220616c7265616479206960448201527f6e7469616c697a65642e000000000000000000000000000000000000000000006064820152608401610493565b6000805473ffffffffffffffffffffffffffffffffffffffff84167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560cd805490911661dead17905561098b611105565b610993611196565b61099b611230565b6109a36112cd565b8015610a0657600080547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60026097541415610a5d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610493565b6002609755610a6a611365565b6000610a78868686866113b8565b9050610a848183611433565b1515600114610afb5760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f7420626520766560448201527f7269666965642e000000000000000000000000000000000000000000000000006064820152608401610493565b8051602080830191909120600081815260cb90925260409091205460ff1615610b8c5760405162461bcd60e51b815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201527f6e2072656365697665642e0000000000000000000000000000000000000000006064820152608401610493565b600081815260c9602052604090205460ff1615610c115760405162461bcd60e51b815260206004820152602260248201527f50726f7669646564206d65737361676520686173206265656e20626c6f636b6560448201527f642e0000000000000000000000000000000000000000000000000000000000006064820152608401610493565b610c4f6040518060400160405280601981526020017f43616e6f6e6963616c5472616e73616374696f6e436861696e00000000000000815250610591565b73ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415610cf05760405162461bcd60e51b815260206004820152603360248201527f43616e6e6f742073656e64204c322d3e4c31206d6573736167657320746f204c60448201527f312073797374656d20636f6e7472616374732e000000000000000000000000006064820152608401610493565b60cd80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff88811691909117909155604051600091891690610d499088906133c7565b6000604051808303816000865af19150503d8060008114610d86576040519150601f19603f3d011682016040523d82523d6000602084013e610d8b565b606091505b505060cd80547fffffffffffffffffffffffff00000000000000000000000000000000000000001661dead179055905080151560011415610e3857600082815260cb602052604090819020805460ff191660011790555173ffffffffffffffffffffffffffffffffffffffff8916907f6166323e9134edd95d3f747dcf3212a095e2916dcfa483d348bcc3716f7f2cfb90610e2b908a908a908a906133d9565b60405180910390a2610e97565b600082905260cc60205260405173ffffffffffffffffffffffffffffffffffffffff8916907fc6ac8f8e058accca572db6f130cf8f9186f28f95658153e1fd8135d094add97590610e8e908a908a908a906133d9565b60405180910390a25b6000833343604051602001610eae93929190613418565b60408051601f198184030181529181528151602092830120600090815260ca9092529020805460ff19166001908117909155609755505050505050505050565b610ef6610f8b565b73ffffffffffffffffffffffffffffffffffffffff8116610f7f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610493565b610f8881611051565b50565b60335473ffffffffffffffffffffffffffffffffffffffff16331461058f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610493565b610ffa611456565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390a1565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6110d0611365565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586110273390565b6000547501000000000000000000000000000000000000000000900460ff1661058f5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b6000547501000000000000000000000000000000000000000000900460ff166112275760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b61058f33611051565b6000547501000000000000000000000000000000000000000000900460ff166112c15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b6065805460ff19169055565b6000547501000000000000000000000000000000000000000000900460ff1661135e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610493565b6001609755565b60655460ff161561058f5760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401610493565b6060848484846040516024016113d1949392919061346a565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcbd4ece9000000000000000000000000000000000000000000000000000000001790529050949350505050565b600061143e826114a8565b801561144f575061144f838361159c565b9392505050565b60655460ff1661058f5760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610493565b6000806114e96040518060400160405280601481526020017f5374617465436f6d6d69746d656e74436861696e000000000000000000000000815250610591565b8351602085015160408087015190517f4d69ee5700000000000000000000000000000000000000000000000000000000815293945073ffffffffffffffffffffffffffffffffffffffff851693634d69ee579361154c93909290916004016134b4565b60206040518083038186803b15801561156457600080fd5b505afa158015611578573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144f919061355f565b600080837342000000000000000000000000000000000000076040516020016115c6929190613581565b60408051601f1981840301815282825280516020918201209083015260009082015260600160408051601f198184030181529082905280516020918201207f420000000000000000000000000000000000000000000000000000000000000091830191909152915060009081906116569060340160408051601f1981840301815291905260608701518751611780565b90925090506001821515146116f95760405162461bcd60e51b815260206004820152604d60248201527f4d6573736167652070617373696e67207072656465706c6f7920686173206e6f60448201527f74206265656e20696e697469616c697a6564206f7220696e76616c696420707260648201527f6f6f662070726f76696465642e00000000000000000000000000000000000000608482015260a401610493565b6000611704826117a9565b90506117758460405160200161171c91815260200190565b60408051601f19818403018152908290527f01000000000000000000000000000000000000000000000000000000000000006020830152906021016040516020818303038152906040528860800151846040015161186d565b979650505050505050565b60006060600061178f86611891565b905061179c8186866118c3565b9250925050935093915050565b6040805160808101825260008082526020820181905291810182905260608101829052906117d68361199e565b90506040518060800160405280611806836000815181106117f9576117f96131d5565b60200260200101516119d1565b8152602001611821836001815181106117f9576117f96131d5565b81526020016118498360028151811061183c5761183c6131d5565b60200260200101516119d8565b81526020016118648360038151811061183c5761183c6131d5565b90529392505050565b60008061187986611891565b905061188781868686611ada565b9695505050505050565b606081805190602001206040516020016118ad91815260200190565b6040516020818303038152906040529050919050565b6000606060006118d285611b10565b905060008060006118e4848a89611c0b565b815192955090935091501580806118f85750815b6119445760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610493565b600081611960576040518060200160405280600081525061198c565b61198c8661196f6001886135cb565b8151811061197f5761197f6131d5565b60200260200101516120a6565b919b919a509098505050505050505050565b604080518082018252600080825260209182015281518083019092528251825280830190820152606090610638906120d0565b6000610638825b6000602182600001511115611a2f5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610493565b6000806000611a3d856122cf565b919450925090506000816001811115611a5857611a586135e2565b14611aa55760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610493565b6000838660200151611ab79190613611565b805190915060208410156118875760208490036101000a90049695505050505050565b6000806000611aea8786866118c3565b915091508180156117755750805160208083019190912087519188019190912014611775565b60606000611b1d8361199e565b90506000815167ffffffffffffffff811115611b3b57611b3b612cc8565b604051908082528060200260200182016040528015611b8057816020015b6040805180820190915260608082526020820152815260200190600190039081611b595790505b50905060005b8251811015611c03576000611bb3848381518110611ba657611ba66131d5565b6020026020010151612620565b90506040518060400160405280828152602001611bcf8361199e565b815250838381518110611be457611be46131d5565b6020026020010181905250508080611bfb90613302565b915050611b86565b509392505050565b60006060818080611c1b876126b0565b90506000869050600080611c42604051806040016040528060608152602001606081525090565b60005b8c51811015612062578c8181518110611c6057611c606131d5565b602002602001015191508284611c769190613611565b9350611c83600188613611565b965083611ce757815180516020909101208514611ce25760405162461bcd60e51b815260206004820152601160248201527f496e76616c696420726f6f7420686173680000000000000000000000000000006044820152606401610493565b611da4565b815151602011611d4957815180516020909101208514611ce25760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610493565b84611d578360000151612833565b14611da45760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610493565b611db060106001613611565b8260200151511415611e29578551841415611dca57612062565b6000868581518110611dde57611dde6131d5565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110611e0957611e096131d5565b60200260200101519050611e1c8161285b565b9650600194505050612050565b60028260200151511415612008576000611e4283612891565b9050600081600081518110611e5957611e596131d5565b016020015160f81c90506000611e70600283613658565b611e7b90600261367a565b90506000611e8c848360ff166128b5565b90506000611e9a8b8a6128b5565b90506000611ea883836128eb565b905060ff851660021480611ebf575060ff85166003145b15611f1557808351148015611ed45750808251145b15611ee657611ee3818b613611565b99505b507f80000000000000000000000000000000000000000000000000000000000000009950612062945050505050565b60ff85161580611f28575060ff85166001145b15611f9a5782518114611f6457507f80000000000000000000000000000000000000000000000000000000000000009950612062945050505050565b611f8b8860200151600181518110611f7e57611f7e6131d5565b602002602001015161285b565b9a509750612050945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e2060448201527f70726566697800000000000000000000000000000000000000000000000000006064820152608401610493565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610493565b8061205a81613302565b915050611c45565b507f800000000000000000000000000000000000000000000000000000000000000084148661209187866128b5565b909e909d50909b509950505050505050505050565b60208101518051606091610638916120c0906001906135cb565b81518110611ba657611ba66131d5565b60606000806120de846122cf565b919350909150600190508160018111156120fa576120fa6135e2565b146121475760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610493565b6040805160208082526104208201909252600091816020015b60408051808201909152600080825260208201528152602001906001900390816121605790505090506000835b86518110156122c4576020821061220c5760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201527f7374206c656e6774682e000000000000000000000000000000000000000000006064820152608401610493565b6000806122496040518060400160405280858c6000015161222d91906135cb565b8152602001858c602001516122429190613611565b90526122cf565b5091509150604051806040016040528083836122659190613611565b8152602001848b6020015161227a9190613611565b81525085858151811061228f5761228f6131d5565b60209081029190910101526122a5600185613611565b93506122b18183613611565b6122bb9084613611565b9250505061218d565b508152949350505050565b6000806000808460000151116123275760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610493565b6020840151805160001a607f811161234c576000600160009450945094505050612619565b60b781116123c85760006123616080836135cb565b9050808760000151116123b65760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610493565b60019550935060009250612619915050565b60bf81116124b75760006123dd60b7836135cb565b9050808760000151116124325760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610493565b600183015160208290036101000a900461244c8183613611565b88511161249b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610493565b6124a6826001613611565b965094506000935061261992505050565b60f781116125325760006124cc60c0836135cb565b9050808760000151116125215760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610493565b600195509350849250612619915050565b600061253f60f7836135cb565b9050808760000151116125945760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610493565b600183015160208290036101000a90046125ae8183613611565b8851116125fd5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420524c50206c6f6e67206c6973742e000000000000000000006044820152606401610493565b612608826001613611565b965094506001935061261992505050565b9193909250565b60606000806000612630856122cf565b91945092509050600081600181111561264b5761264b6135e2565b146126985760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610493565b6126a785602001518484612997565b95945050505050565b60606000825160026126c2919061369d565b67ffffffffffffffff8111156126da576126da612cc8565b6040519080825280601f01601f191660200182016040528015612704576020820181803683370190505b50905060005b835181101561282c576004848281518110612727576127276131d5565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016901c8261275c83600261369d565b8151811061276c5761276c6131d5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060108482815181106127af576127af6131d5565b01602001516127c1919060f81c613658565b60f81b826127d083600261369d565b6127db906001613611565b815181106127eb576127eb6131d5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508061282481613302565b91505061270a565b5092915050565b600060208251101561284757506020015190565b8180602001905181019061063891906136da565b6000606060208360000151101561287c5761287583612a76565b9050612888565b61288583612620565b90505b61144f81612833565b60606106386128b08360200151600081518110611ba657611ba66131d5565b6126b0565b6060825182106128d45750604080516020810190915260008152610638565b61144f83838486516128e691906135cb565b612a81565b6000805b8084511180156128ff5750808351115b80156129805750828181518110612918576129186131d5565b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916848281518110612957576129576131d5565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016145b1561144f578061298f81613302565b9150506128ef565b606060008267ffffffffffffffff8111156129b4576129b4612cc8565b6040519080825280601f01601f1916602001820160405280156129de576020820181803683370190505b5090508051600014156129f257905061144f565b60006129fe8587613611565b90506020820160005b612a126020876136f3565b811015612a495782518252612a28602084613611565b9250612a35602083613611565b915080612a4181613302565b915050612a07565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b606061063882612c02565b606081612a8f81601f613611565b1015612add5760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610493565b82612ae88382613611565b1015612b365760405162461bcd60e51b815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610493565b612b408284613611565b84511015612b905760405162461bcd60e51b815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610493565b606082158015612baf5760405191506000825260208201604052612bf9565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612be8578051835260209283019201612bd0565b5050858452601f01601f1916604052505b50949350505050565b6060610638826020015160008460000151612997565b600060208284031215612c2a57600080fd5b5035919050565b60008060208385031215612c4457600080fd5b823567ffffffffffffffff80821115612c5c57600080fd5b818501915085601f830112612c7057600080fd5b813581811115612c7f57600080fd5b8660208260051b8501011115612c9457600080fd5b60209290920196919550909350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f8857600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612d1a57612d1a612cc8565b60405290565b6040805190810167ffffffffffffffff81118282101715612d1a57612d1a612cc8565b604051601f8201601f1916810167ffffffffffffffff81118282101715612d6c57612d6c612cc8565b604052919050565b600067ffffffffffffffff831115612d8e57612d8e612cc8565b612da16020601f19601f86011601612d43565b9050828152838383011115612db557600080fd5b828260208301376000602084830101529392505050565b600082601f830112612ddd57600080fd5b61144f83833560208501612d74565b803563ffffffff81168114612e0057600080fd5b919050565b600080600060608486031215612e1a57600080fd5b8335612e2581612ca6565b9250602084013567ffffffffffffffff811115612e4157600080fd5b612e4d86828701612dcc565b925050612e5c60408501612dec565b90509250925092565b600060208284031215612e7757600080fd5b813567ffffffffffffffff811115612e8e57600080fd5b8201601f81018413612e9f57600080fd5b612eae84823560208401612d74565b949350505050565b60008060008060008060c08789031215612ecf57600080fd5b8635612eda81612ca6565b95506020870135612eea81612ca6565b9450604087013567ffffffffffffffff811115612f0657600080fd5b612f1289828a01612dcc565b94505060608701359250612f2860808801612dec565b9150612f3660a08801612dec565b90509295509295509295565b600060208284031215612f5457600080fd5b813561144f81612ca6565b600060a08284031215612f7157600080fd5b612f79612cf7565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff811115612fb757600080fd5b612fc384828501612dcc565b60808301525092915050565b600060408284031215612fe157600080fd5b612fe9612d20565b90508135815260208083013567ffffffffffffffff8082111561300b57600080fd5b818501915085601f83011261301f57600080fd5b81358181111561303157613031612cc8565b8060051b9150613042848301612d43565b818152918301840191848101908884111561305c57600080fd5b938501935b8385101561307a57843582529385019390850190613061565b808688015250505050505092915050565b600060a0828403121561309d57600080fd5b6130a5612cf7565b905081358152602082013567ffffffffffffffff808211156130c657600080fd5b6130d285838601612f5f565b602084015260408401359150808211156130eb57600080fd5b6130f785838601612fcf565b6040840152606084013591508082111561311057600080fd5b61311c85838601612dcc565b6060840152608084013591508082111561313557600080fd5b50612fc384828501612dcc565b600080600080600060a0868803121561315a57600080fd5b853561316581612ca6565b9450602086013561317581612ca6565b9350604086013567ffffffffffffffff8082111561319257600080fd5b61319e89838a01612dcc565b94506060880135935060808801359150808211156131bb57600080fd5b506131c88882890161308b565b9150509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261323857600080fd5b9190910192915050565b600060a0823603121561325457600080fd5b61325c612cf7565b823561326781612ca6565b8152602083013561327781612ca6565b6020820152604083013567ffffffffffffffff8082111561329757600080fd5b6132a336838701612dcc565b60408401526060850135606084015260808501359150808211156132c657600080fd5b50612fc33682860161308b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613334576133346132d3565b5060010190565b60005b8381101561335657818101518382015260200161333e565b83811115613365576000848401525b50505050565b6000815180845261338381602086016020860161333b565b601f01601f19169290920160200192915050565b60208152600061144f602083018461336b565b6000602082840312156133bc57600080fd5b815161144f81612ca6565b6000825161323881846020870161333b565b73ffffffffffffffffffffffffffffffffffffffff84168152606060208201526000613408606083018561336b565b9050826040830152949350505050565b6000845161342a81846020890161333b565b60609490941b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001691909301908152601481019190915260340192915050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250608060408301526134a3608083018561336b565b905082606083015295945050505050565b8381526000602060608184015284516060840152808501516080840152604085015160a0840152606085015160c0840152608085015160a060e08501526134ff61010085018261336b565b905083810360408501526040810185518252828601516040848401528181518084526060850191508583019450600093505b808410156135515784518252938501936001939093019290850190613531565b509998505050505050505050565b60006020828403121561357157600080fd5b8151801515811461144f57600080fd5b6000835161359381846020880161333b565b60609390931b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190920190815260140192915050565b6000828210156135dd576135dd6132d3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60008219821115613624576136246132d3565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060ff83168061366b5761366b613629565b8060ff84160691505092915050565b600060ff821660ff841680821015613694576136946132d3565b90039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156136d5576136d56132d3565b500290565b6000602082840312156136ec57600080fd5b5051919050565b60008261370257613702613629565b50049056fea26469706673582212202de197a29c4cdce4170574fe7ddb3adcfb6375d36dc28b79414f33371d02f4c364736f6c63430008090033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.