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 Source Code Verified (Exact Match)
Contract Name:
L1CrossDomainMessenger
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 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 { AddressAliasHelper } from "../../standards/AddressAliasHelper.sol"; import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol"; import { Lib_BVMCodec } from "../../libraries/codec/Lib_BVMCodec.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 { ICanonicalTransactionChain } from "../rollup/ICanonicalTransactionChain.sol"; import { IStateCommitmentChain } from "../rollup/IStateCommitmentChain.sol"; /* External Imports */ 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 L1CrossDomainMessenger * @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 L1CrossDomainMessenger 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; address internal xDomainMsgSender = Lib_DefaultValues.DEFAULT_XDOMAIN_SENDER; address internal pauseOwner ; /*************** * 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)) {} /******************** * Public Functions * ********************/ /** * @param _libAddressManager Address of the Address Manager. */ // slither-disable-next-line external-function 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 relaying. */ function pause() external onlyOwner { _pause(); } /** * UnPause relaying. */ function unpause() external onlyOwner { _unpause(); } function setPauseOwner(address _pauseOwner) external onlyOwner { pauseOwner = _pauseOwner; } function getPauseOwner() public view returns (address) { return pauseOwner; } function pauseByPOwner() external { require( pauseOwner == msg.sender, "msg.sender shoule be pauseowner." ); _pause(); } /** * 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); } // slither-disable-next-line external-function function xDomainMessageSender() public view 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. */ // slither-disable-next-line external-function function sendMessage( address _target, bytes memory _message, uint32 _gasLimit ) public { address bvmCanonicalTransactionChain = resolve("CanonicalTransactionChain"); // Use the CTC queue length as nonce uint40 nonce = ICanonicalTransactionChain(bvmCanonicalTransactionChain).getQueueLength(); bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( _target, msg.sender, _message, nonce ); // slither-disable-next-line reentrancy-events _sendXDomainMessage(bvmCanonicalTransactionChain, xDomainCalldata, _gasLimit); // slither-disable-next-line reentrancy-events emit SentMessage(_target, msg.sender, _message, nonce, _gasLimit); } /** * Relays a cross domain message to a contract. * @inheritdoc IL1CrossDomainMessenger */ // slither-disable-next-line external-function function relayMessage( address _target, address _sender, bytes memory _message, uint256 _messageNonce, L2MessageInclusionProof memory _proof ) public nonReentrant whenNotPaused { bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( _target, _sender, _message, _messageNonce ); 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; // slither-disable-next-line reentrancy-no-eth, reentrancy-events, reentrancy-benign (bool success, ) = _target.call(_message); // slither-disable-next-line reentrancy-benign 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) { // slither-disable-next-line reentrancy-no-eth successfulMessages[xDomainCalldataHash] = true; // slither-disable-next-line reentrancy-events emit RelayedMessage(xDomainCalldataHash); } else { // slither-disable-next-line reentrancy-events emit FailedRelayedMessage(xDomainCalldataHash); } // 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)); // slither-disable-next-line reentrancy-benign relayedMessages[relayId] = true; } /** * Replays a cross domain message to the target messenger. * @inheritdoc IL1CrossDomainMessenger */ // slither-disable-next-line external-function function replayMessage( address _target, address _sender, bytes memory _message, uint256 _queueIndex, uint32 _oldGasLimit, uint32 _newGasLimit ) public { // Verify that the message is in the queue: address canonicalTransactionChain = resolve("CanonicalTransactionChain"); Lib_BVMCodec.QueueElement memory element = ICanonicalTransactionChain( canonicalTransactionChain ).getQueueElement(_queueIndex); // Compute the calldata that was originally used to send the message. bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata( _target, _sender, _message, _queueIndex ); // Compute the transactionHash bytes32 transactionHash = keccak256( abi.encode( AddressAliasHelper.applyL1ToL2Alias(address(this)), Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, _oldGasLimit, xDomainCalldata ) ); // Now check that the provided message data matches the one in the queue element. require( transactionHash == element.transactionHash, "Provided message has not been enqueued." ); // Send the same message but with the new gas limit. _sendXDomainMessage(canonicalTransactionChain, xDomainCalldata, _newGasLimit); } /********************** * 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 bvmStateCommitmentChain = IStateCommitmentChain( resolve("StateCommitmentChain") ); return (bvmStateCommitmentChain.insideFraudProofWindow(_proof.stateRootBatchHeader) == false && bvmStateCommitmentChain.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_BVMCodec.EVMAccount memory account = Lib_BVMCodec.decodeEVMAccount( encodedMessagePassingAccount ); return Lib_SecureMerkleTrie.verifyInclusionProof( abi.encodePacked(storageKey), abi.encodePacked(uint8(1)), _proof.storageTrieWitness, account.storageRoot ); } /** * Sends a cross domain message. * @param _canonicalTransactionChain Address of the CanonicalTransactionChain instance. * @param _message Message to send. * @param _gasLimit BVM gas limit for the message. */ function _sendXDomainMessage( address _canonicalTransactionChain, bytes memory _message, uint256 _gasLimit ) internal { // slither-disable-next-line reentrancy-events ICanonicalTransactionChain(_canonicalTransactionChain).enqueue( Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER, _gasLimit, _message ); } }
// SPDX-License-Identifier: Apache-2.0 /* * Copyright 2019-2021, Offchain Labs, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity ^0.8.7; library AddressAliasHelper { uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); /// @notice Utility function that converts the address in the L1 that submitted a tx to /// the inbox to the msg.sender viewed in the L2 /// @param l1Address the address in the L1 that triggered the tx to L2 /// @return l2Address L2 address as viewed in msg.sender function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { unchecked { l2Address = address(uint160(l1Address) + offset); } } /// @notice Utility function that converts the msg.sender viewed in the L2 to the /// address in the L1 that submitted a tx to the inbox /// @param l2Address L2 address as viewed in msg.sender /// @return l1Address the address in the L1 that triggered the tx to L2 function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { unchecked { l1Address = address(uint160(l2Address) - offset); } } }
// 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; /* 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; /* 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; /** * @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 BVM_MANTLE = payable(0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000); address payable internal constant BVM_ETH = payable(0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111); 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; /* 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_BVMCodec */ library Lib_BVMCodec { /********* * 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 signature; 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 BVM transaction. * @param _transaction BVM 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 BVM transaction. * @param _transaction BVM 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_BVMCodec.ChainBatchHeader memory _batchHeader) internal pure returns (bytes32) { return keccak256( abi.encode( _batchHeader.batchRoot, _batchHeader.batchSize, _batchHeader.prevTotalElements, _batchHeader.signature, _batchHeader.extraData ) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* Library Imports */ import { Lib_BVMCodec } from "../../libraries/codec/Lib_BVMCodec.sol"; /* Interface Imports */ import { ICrossDomainMessenger } from "../../libraries/bridge/ICrossDomainMessenger.sol"; /** * @title IL1CrossDomainMessenger */ interface IL1CrossDomainMessenger is ICrossDomainMessenger { /******************* * Data Structures * *******************/ struct L2MessageInclusionProof { bytes32 stateRoot; Lib_BVMCodec.ChainBatchHeader stateRootBatchHeader; Lib_BVMCodec.ChainInclusionProof stateRootProof; bytes stateTrieWitness; bytes storageTrieWitness; } /******************** * 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; }
// 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_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.5.0 <0.9.0; /* Library Imports */ import { Lib_BVMCodec } from "../../libraries/codec/Lib_BVMCodec.sol"; /* Interface Imports */ import { IChainStorageContainer } from "./IChainStorageContainer.sol"; /** * @title ICanonicalTransactionChain */ interface ICanonicalTransactionChain { /********** * Events * **********/ event L2GasParamsUpdated( uint256 l2GasDiscountDivisor, uint256 enqueueGasCost, uint256 enqueueL2GasPrepaid ); event TransactionEnqueued( address indexed _l1TxOrigin, address indexed _target, uint256 _gasLimit, bytes _data, uint256 indexed _queueIndex, uint256 _timestamp ); event QueueBatchAppended( uint256 _startingQueueIndex, uint256 _numQueueElements, uint256 _totalElements ); event SequencerBatchAppended( uint256 _startingQueueIndex, uint256 _numQueueElements, uint256 _totalElements ); event TransactionBatchAppended( uint256 indexed _batchIndex, bytes32 _batchRoot, uint256 _batchSize, uint256 _prevTotalElements, bytes _signature, bytes _extraData ); event CTCBatchReset( uint256 indexed _batchIndex, uint40 _nextqIndex, uint40 _totalElement, uint40 _batchSize, uint40 _numQueuedTransactions , uint40 _timestamp, uint40 _blockNumber ); /*********** * Structs * ***********/ struct BatchContext { uint256 numSequencedTransactions; uint256 numSubsequentQueueTransactions; uint256 timestamp; uint256 blockNumber; } /******************************* * Authorized Setter Functions * *******************************/ /** * Allows the Burn Admin to update the parameters which determine the amount of gas to burn. * The value of enqueueL2GasPrepaid is immediately updated as well. */ function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost) external; /******************** * Public Functions * ********************/ /** * Accesses the batch storage container. * @return Reference to the batch storage container. */ function batches() external view returns (IChainStorageContainer); /** * 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); /** * Returns the index of the next element to be enqueued. * @return Index for the next queue element. */ function getNextQueueIndex() external view returns (uint40); /** * Gets the queue element at a particular index. * @param _index Index of the queue element to access. * @return _element Queue element at the given index. */ function getQueueElement(uint256 _index) external view returns (Lib_BVMCodec.QueueElement memory _element); /** * Returns the timestamp of the last transaction. * @return Timestamp for the last transaction. */ function getLastTimestamp() external view returns (uint40); /** * Returns the blocknumber of the last transaction. * @return Blocknumber for the last transaction. */ function getLastBlockNumber() external view returns (uint40); /** * Get the number of queue elements which have not yet been included. * @return Number of pending queue elements. */ function getNumPendingQueueElements() external view returns (uint40); /** * Retrieves the length of the queue, including * both pending and canonical transactions. * @return Length of the queue. */ function getQueueLength() external view returns (uint40); /** * Adds a transaction to the queue. * @param _target Target contract to send the transaction to. * @param _gasLimit Gas limit for the given transaction. * @param _data Transaction data. */ function enqueue( address _target, uint256 _gasLimit, bytes memory _data ) external; /** * Allows the sequencer to append a batch of transactions. * @dev This function uses a custom encoding scheme for efficiency reasons. * .param _shouldStartAtElement Specific batch we expect to start appending to. * .param _totalElementsToAppend Total number of batch elements we expect to append. * .param _contexts Array of batch contexts. * .param _transactionDataFields Array of raw transaction data. */ function appendSequencerBatch( // uint40 _shouldStartAtElement, // uint24 _totalElementsToAppend, // BatchContext[] _contexts, // bytes[] _transactionDataFields ) external; function resetIndex(uint256 _batchIndex, uint40 _totalElement, uint40 _batchSize, uint40 _nextqIndex,uint40 _numQueuedTransactions , uint40 _timestamp, uint40 _blockNumber) external; }
// SPDX-License-Identifier: MIT pragma solidity >0.5.0 <0.9.0; /* Library Imports */ import { Lib_BVMCodec } from "../../libraries/codec/Lib_BVMCodec.sol"; /** * @title IStateCommitmentChain */ interface IStateCommitmentChain { /********** * Events * **********/ event StateBatchAppended( uint256 indexed _batchIndex, bytes32 _batchRoot, uint256 _batchSize, uint256 _prevTotalElements, bytes _signature, bytes _extraData ); event StateBatchDeleted(uint256 indexed _batchIndex, bytes32 _batchRoot); event DistributeTssReward( uint256 indexed _startBlockNumber, uint256 _length, uint256 indexed _batchTime, address[] _tssMembers ); event RollBackL2Chain(uint256 indexed _startBlockNumber); /******************** * 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. * @param _signature tss group signature of state batches. */ function appendStateBatch(bytes32[] calldata _batch, uint256 _shouldStartAtElement, bytes memory _signature) external; /** * Deletes all state roots after (and including) a given batch. * @param _batchHeader Header of the batch to start deleting from. */ function deleteStateBatch(Lib_BVMCodec.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_BVMCodec.ChainBatchHeader memory _batchHeader, Lib_BVMCodec.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_BVMCodec.ChainBatchHeader memory _batchHeader) external view returns (bool _inside); /** * Emit event to notify sequencers to roll back. * @param _shouldRollBack roll back to should start . * @param _shouldStartAtElement Index of the element at which this batch should start * @param _signature signature of rollback message */ function rollBackL2Chain(uint256 _shouldRollBack,uint256 _shouldStartAtElement, bytes memory _signature) external; }
// 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) (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 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_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; /** * @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_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); } }
// 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; /** * @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.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); /************* * 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.5.0 <0.9.0; /** * @title IChainStorageContainer */ interface IChainStorageContainer { /******************** * Public Functions * ********************/ /** * Sets the container's global metadata field. We're using `bytes27` here because we use five * bytes to maintain the length of the underlying data structure, meaning we have an extra * 27 bytes to store arbitrary data. * @param _globalMetadata New global metadata to set. */ function setGlobalMetadata(bytes27 _globalMetadata) external; /** * Retrieves the container's global metadata field. * @return Container global metadata field. */ function getGlobalMetadata() external view returns (bytes27); /** * Retrieves the number of objects stored in the container. * @return Number of objects in the container. */ function length() external view returns (uint256); /** * Pushes an object into the container. * @param _object A 32 byte value to insert into the container. */ function push(bytes32 _object) external; /** * Pushes an object into the container. Function allows setting the global metadata since * we'll need to touch the "length" storage slot anyway, which also contains the global * metadata (it's an optimization). * @param _object A 32 byte value to insert into the container. * @param _globalMetadata New global metadata for the container. */ function push(bytes32 _object, bytes27 _globalMetadata) external; /** * Retrieves an object from the container. * @param _index Index of the particular object to access. * @return 32 byte object value. */ function get(uint256 _index) external view returns (bytes32); /** * Removes all objects after and including a given index. * @param _index Object index to delete from. */ function deleteElementsAfterInclusive(uint256 _index) external; /** * Removes all objects after and including a given index. Also allows setting the global * metadata field. * @param _index Object index to delete from. * @param _globalMetadata New global metadata for the container. */ function deleteElementsAfterInclusive(uint256 _index, bytes27 _globalMetadata) external; }
// 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 // 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) (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); } } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "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":"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":"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":[{"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":[],"name":"getPauseOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"pauseByPOwner","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":"signature","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct Lib_BVMCodec.ChainBatchHeader","name":"stateRootBatchHeader","type":"tuple"},{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"}],"internalType":"struct Lib_BVMCodec.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":"address","name":"_pauseOwner","type":"address"}],"name":"setPauseOwner","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
608060405260cc80546001600160a01b03191661dead17905534801561002457600080fd5b50600080546001600160a01b0319169055613266806100446000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c80637738034c116100b8578063b1b1b2091161007c578063b1b1b20914610255578063c4d66de814610278578063c6b94ab01461028b578063cba4c652146102ae578063d9ce1901146102c1578063f2fde38b146102d457600080fd5b80637738034c1461021057806381ada46c146102185780638456cb591461022b5780638da5cb5b146102335780638ec6a68a1461024457600080fd5b8063461a4478116100ff578063461a4478146101cf5780635c975abb146101e25780636e296e45146101ed5780636f1c8d47146101f5578063715018a61461020857600080fd5b80630ecf2eea1461013c57806321d800ec14610151578063299ca478146101895780633dbb202b146101b45780633f4ba83a146101c7575b600080fd5b61014f61014a3660046127c9565b6102e7565b005b61017461015f3660046127c9565b60ca6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b60005461019c906001600160a01b031681565b6040516001600160a01b039091168152602001610180565b61014f6101c2366004612939565b610332565b61014f61045c565b61019c6101dd366004612998565b61046e565b60655460ff16610174565b61019c6104f5565b61014f6102033660046129e8565b61056a565b61014f610704565b61014f610716565b61014f6102263660046127c9565b610778565b61014f6107c0565b6033546001600160a01b031661019c565b60cd546001600160a01b031661019c565b6101746102633660046127c9565b60cb6020526000908152604090205460ff1681565b61014f610286366004612a73565b6107c8565b6101746102993660046127c9565b60c96020526000908152604090205460ff1681565b61014f6102bc366004612a73565b6109a4565b61014f6102cf366004612be1565b6109ce565b61014f6102e2366004612a73565b610daa565b6102ef610e23565b600081815260c96020526040808220805460ff191660011790555182917ff52508d5339edf0d7e5060a416df98db067af561bdc60872d29c0439eaa13a0291a250565b600061036e6040518060400160405280601981526020017821b0b737b734b1b0b62a3930b739b0b1ba34b7b721b430b4b760391b81525061046e565b90506000816001600160a01b031663b8f770056040518163ffffffff1660e01b815260040160206040518083038186803b1580156103ab57600080fd5b505afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190612d2e565b905060006103fa8633878564ffffffffff16610e7d565b905061040d83828663ffffffff16610eca565b856001600160a01b03167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3387858860405161044c9493929190612da5565b60405180910390a2505050505050565b610464610e23565b61046c610f38565b565b6000805460405163bf40fac160e01b81526001600160a01b039091169063bf40fac19061049f908590600401612ded565b60206040518083038186803b1580156104b757600080fd5b505afa1580156104cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ef9190612e00565b92915050565b60cc546000906001600160a01b031661dead141561055a5760405162461bcd60e51b815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f74207365740060448201526064015b60405180910390fd5b5060cc546001600160a01b031690565b60006105a66040518060400160405280601981526020017821b0b737b734b1b0b62a3930b739b0b1ba34b7b721b430b4b760391b81525061046e565b60405163153f8c5f60e11b8152600481018690529091506000906001600160a01b03831690632a7f18be9060240160606040518083038186803b1580156105ec57600080fd5b505afa158015610600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106249190612e1d565b9050600061063489898989610e7d565b9050600073111100000000000000000000000000000000111130016007602160991b01878460405160200161066c9493929190612e81565b604051602081830303815290604052805190602001209050826000015181146106e75760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520686173206e6f74206265656e20656e60448201526638bab2bab2b21760c91b6064820152608401610551565b6106f884838763ffffffff16610eca565b50505050505050505050565b61070c610e23565b61046c6000610f8a565b60cd546001600160a01b031633146107705760405162461bcd60e51b815260206004820181905260248201527f6d73672e73656e6465722073686f756c652062652070617573656f776e65722e6044820152606401610551565b61046c610fdc565b610780610e23565b600081815260c96020526040808220805460ff191690555182917f52c8a2680a9f4cc0ad0bf88f32096eadbebf0646ea611d93a0ce6a29a024040591a250565b610770610e23565b600054600160a81b900460ff16158080156107f057506000546001600160a01b90910460ff16105b806108115750303b1580156108115750600054600160a01b900460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610551565b6000805460ff60a01b1916600160a01b17905580156108a1576000805460ff60a81b1916600160a81b1790555b6000546001600160a01b03161561090d5760405162461bcd60e51b815260206004820152602a60248201527f4c3143726f7373446f6d61696e4d657373656e67657220616c72656164792069604482015269373a34b0b634bd32b21760b11b6064820152608401610551565b600080546001600160a01b0384166001600160a01b03199182161790915560cc805490911661dead179055610940611019565b610948611042565b610950611074565b6109586110a9565b80156109a0576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6109ac610e23565b60cd80546001600160a01b0319166001600160a01b0392909216919091179055565b60026097541415610a215760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610551565b6002609755610a2e6110d9565b6000610a3c86868686610e7d565b9050610a48818361111f565b1515600114610aa95760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f742062652076656044820152663934b334b2b21760c91b6064820152608401610551565b8051602080830191909120600081815260cb90925260409091205460ff1615610b285760405162461bcd60e51b815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201526a37103932b1b2b4bb32b21760a91b6064820152608401610551565b600081815260c9602052604090205460ff1615610b925760405162461bcd60e51b815260206004820152602260248201527f50726f7669646564206d65737361676520686173206265656e20626c6f636b65604482015261321760f11b6064820152608401610551565b610bcc6040518060400160405280601981526020017821b0b737b734b1b0b62a3930b739b0b1ba34b7b721b430b4b760391b81525061046e565b6001600160a01b0316876001600160a01b03161415610c495760405162461bcd60e51b815260206004820152603360248201527f43616e6e6f742073656e64204c322d3e4c31206d6573736167657320746f204c604482015272189039bcb9ba32b69031b7b73a3930b1ba399760691b6064820152608401610551565b60cc80546001600160a01b0319166001600160a01b0388811691909117909155604051600091891690610c7d908890612eb9565b6000604051808303816000865af19150503d8060008114610cba576040519150601f19603f3d011682016040523d82523d6000602084013e610cbf565b606091505b505060cc80546001600160a01b03191661dead179055905080151560011415610d2757600082815260cb6020526040808220805460ff191660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2610d53565b60405182907f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f90600090a25b6000833343604051602001610d6a93929190612ed5565b60408051601f198184030181529181528151602092830120600090815260ca9092529020805460ff19166001908117909155609755505050505050505050565b610db2610e23565b6001600160a01b038116610e175760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610551565b610e2081610f8a565b50565b6033546001600160a01b0316331461046c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610551565b606084848484604051602401610e969493929190612f14565b60408051601f198184030181529190526020810180516001600160e01b031663cbd4ece960e01b1790529050949350505050565b60405163037f703f60e51b81526001600160a01b03841690636fee07e090610f01906007602160991b019085908790600401612f51565b600060405180830381600087803b158015610f1b57600080fd5b505af1158015610f2f573d6000803e3d6000fd5b50505050505050565b610f40611142565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b610fe46110d9565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f6d3390565b600054600160a81b900460ff1661046c5760405162461bcd60e51b815260040161055190612f78565b600054600160a81b900460ff1661106b5760405162461bcd60e51b815260040161055190612f78565b61046c33610f8a565b600054600160a81b900460ff1661109d5760405162461bcd60e51b815260040161055190612f78565b6065805460ff19169055565b600054600160a81b900460ff166110d25760405162461bcd60e51b815260040161055190612f78565b6001609755565b60655460ff161561046c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610551565b600061112a8261118b565b801561113b575061113b83836112d8565b9392505050565b60655460ff1661046c5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610551565b6000806111c36040518060400160405280601481526020017329ba30ba32a1b7b6b6b4ba36b2b73a21b430b4b760611b81525061046e565b602084015160405163011343b360e71b81529192506001600160a01b038316916389a1d980916111f591600401613019565b60206040518083038186803b15801561120d57600080fd5b505afa158015611221573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611245919061302c565b15801561113b575082516020840151604080860151905163b768bb1760e01b81526001600160a01b0385169363b768bb179361128893919290919060040161304e565b60206040518083038186803b1580156112a057600080fd5b505afa1580156112b4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b919061302c565b600080836007602160991b016040516020016112f59291906130c6565b60408051601f1981840301815282825280516020918201209083015260009082015260600160408051601f19818403018152908290528051602091820120602160f91b91830191909152915060009081906113699060340160408051601f1981840301815291905260608701518751611467565b90925090506001821515146113fc5760405162461bcd60e51b815260206004820152604d60248201527f4d6573736167652070617373696e67207072656465706c6f7920686173206e6f60448201527f74206265656e20696e697469616c697a6564206f7220696e76616c696420707260648201526c37b7b310383937bb34b232b21760991b608482015260a401610551565b600061140782611490565b905061145c8460405160200161141f91815260200190565b60408051601f1981840301815290829052600160f81b60208301529060210160405160208183030381529060405288608001518460400151611554565b979650505050505050565b60006060600061147686611578565b90506114838186866115aa565b9250925050935093915050565b6040805160808101825260008082526020820181905291810182905260608101829052906114bd83611685565b905060405180608001604052806114ed836000815181106114e0576114e06130fd565b60200260200101516116b8565b8152602001611508836001815181106114e0576114e06130fd565b815260200161153083600281518110611523576115236130fd565b60200260200101516116bf565b815260200161154b83600381518110611523576115236130fd565b90529392505050565b60008061156086611578565b905061156e818686866117c1565b9695505050505050565b6060818051906020012060405160200161159491815260200190565b6040516020818303038152906040529050919050565b6000606060006115b9856117f7565b905060008060006115cb848a896118f1565b815192955090935091501580806115df5750815b61162b5760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610551565b6000816116475760405180602001604052806000815250611673565b61167386611656600188613129565b81518110611666576116666130fd565b6020026020010151611d15565b919b919a509098505050505050505050565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906104ef90611d3f565b60006104ef825b60006021826000015111156117165760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610551565b600080600061172485611f2b565b91945092509050600081600181111561173f5761173f613140565b1461178c5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610551565b600083866020015161179e9190613156565b8051909150602084101561156e5760208490036101000a90049695505050505050565b60008060006117d18786866115aa565b9150915081801561145c575080516020808301919091208751918801919091201461145c565b6060600061180483611685565b9050600081516001600160401b03811115611821576118216127f7565b60405190808252806020026020018201604052801561186657816020015b604080518082019091526060808252602082015281526020019060019003908161183f5790505b50905060005b82518110156118e957600061189984838151811061188c5761188c6130fd565b6020026020010151612275565b905060405180604001604052808281526020016118b583611685565b8152508383815181106118ca576118ca6130fd565b60200260200101819052505080806118e19061316e565b91505061186c565b509392505050565b6000606081808061190187612305565b90506000869050600080611928604051806040016040528060608152602001606081525090565b60005b8c51811015611ced578c8181518110611946576119466130fd565b60200260200101519150828461195c9190613156565b9350611969600188613156565b9650836119c1578151805160209091012085146119bc5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b6044820152606401610551565b611a7e565b815151602011611a23578151805160209091012085146119bc5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610551565b84611a31836000015161243f565b14611a7e5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610551565b611a8a60106001613156565b8260200151511415611b03578551841415611aa457611ced565b6000868581518110611ab857611ab86130fd565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110611ae357611ae36130fd565b60200260200101519050611af681612467565b9650600194505050611cdb565b60028260200151511415611c93576000611b1c8361249d565b9050600081600081518110611b3357611b336130fd565b016020015160f81c90506000611b4a60028361319f565b611b559060026131c1565b90506000611b66848360ff166124c1565b90506000611b748b8a6124c1565b90506000611b8283836124f7565b905060ff851660021480611b99575060ff85166003145b15611bd357808351148015611bae5750808251145b15611bc057611bbd818b613156565b99505b50600160ff1b9950611ced945050505050565b60ff85161580611be6575060ff85166001145b15611c3c5782518114611c065750600160ff1b9950611ced945050505050565b611c2d8860200151600181518110611c2057611c206130fd565b6020026020010151612467565b9a509750611cdb945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b6064820152608401610551565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610551565b80611ce58161316e565b91505061192b565b50600160ff1b841486611d0087866124c1565b909e909d50909b509950505050505050505050565b602081015180516060916104ef91611d2f90600190613129565b8151811061188c5761188c6130fd565b6060600080611d4d84611f2b565b91935090915060019050816001811115611d6957611d69613140565b14611db65760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610551565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081611dcf5790505090506000835b8651811015611f205760208210611e685760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b6064820152608401610551565b600080611ea56040518060400160405280858c60000151611e899190613129565b8152602001858c60200151611e9e9190613156565b9052611f2b565b509150915060405180604001604052808383611ec19190613156565b8152602001848b60200151611ed69190613156565b815250858581518110611eeb57611eeb6130fd565b6020908102919091010152611f01600185613156565b9350611f0d8183613156565b611f179084613156565b92505050611dfc565b508152949350505050565b600080600080846000015111611f835760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610551565b6020840151805160001a607f8111611fa857600060016000945094509450505061226e565b60b78111612024576000611fbd608083613129565b9050808760000151116120125760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610551565b6001955093506000925061226e915050565b60bf811161211357600061203960b783613129565b90508087600001511161208e5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610551565b600183015160208290036101000a90046120a88183613156565b8851116120f75760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610551565b612102826001613156565b965094506000935061226e92505050565b60f7811161218e57600061212860c083613129565b90508087600001511161217d5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610551565b60019550935084925061226e915050565b600061219b60f783613129565b9050808760000151116121f05760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610551565b600183015160208290036101000a900461220a8183613156565b8851116122525760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b6044820152606401610551565b61225d826001613156565b965094506001935061226e92505050565b9193909250565b6060600080600061228585611f2b565b9194509250905060008160018111156122a0576122a0613140565b146122ed5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610551565b6122fc85602001518484612573565b95945050505050565b606060008251600261231791906131e4565b6001600160401b0381111561232e5761232e6127f7565b6040519080825280601f01601f191660200182016040528015612358576020820181803683370190505b50905060005b835181101561243857600484828151811061237b5761237b6130fd565b01602001516001600160f81b031916901c826123988360026131e4565b815181106123a8576123a86130fd565b60200101906001600160f81b031916908160001a90535060108482815181106123d3576123d36130fd565b01602001516123e5919060f81c61319f565b60f81b826123f48360026131e4565b6123ff906001613156565b8151811061240f5761240f6130fd565b60200101906001600160f81b031916908160001a905350806124308161316e565b91505061235e565b5092915050565b600060208251101561245357506020015190565b818060200190518101906104ef9190613203565b600060606020836000015110156124885761248183612651565b9050612494565b61249183612275565b90505b61113b8161243f565b60606104ef6124bc836020015160008151811061188c5761188c6130fd565b612305565b6060825182106124e057506040805160208101909152600081526104ef565b61113b83838486516124f29190613129565b61265c565b6000805b80845111801561250b5750808351115b801561255c5750828181518110612524576125246130fd565b602001015160f81c60f81b6001600160f81b03191684828151811061254b5761254b6130fd565b01602001516001600160f81b031916145b1561113b578061256b8161316e565b9150506124fb565b60606000826001600160401b0381111561258f5761258f6127f7565b6040519080825280601f01601f1916602001820160405280156125b9576020820181803683370190505b5090508051600014156125cd57905061113b565b60006125d98587613156565b90506020820160005b6125ed60208761321c565b8110156126245782518252612603602084613156565b9250612610602083613156565b91508061261c8161316e565b9150506125e2565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606104ef826127b3565b60608161266a81601f613156565b10156126a95760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610551565b826126b48382613156565b10156126f35760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610551565b6126fd8284613156565b845110156127415760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610551565b60608215801561276057604051915060008252602082016040526127aa565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612799578051835260209283019201612781565b5050858452601f01601f1916604052505b50949350505050565b60606104ef826020015160008460000151612573565b6000602082840312156127db57600080fd5b5035919050565b6001600160a01b0381168114610e2057600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b038111828210171561282f5761282f6127f7565b60405290565b604080519081016001600160401b038111828210171561282f5761282f6127f7565b60405160a081016001600160401b038111828210171561282f5761282f6127f7565b604051601f8201601f191681016001600160401b03811182821017156128a1576128a16127f7565b604052919050565b60006001600160401b038311156128c2576128c26127f7565b6128d5601f8401601f1916602001612879565b90508281528383830111156128e957600080fd5b828260208301376000602084830101529392505050565b600082601f83011261291157600080fd5b61113b838335602085016128a9565b803563ffffffff8116811461293457600080fd5b919050565b60008060006060848603121561294e57600080fd5b8335612959816127e2565b925060208401356001600160401b0381111561297457600080fd5b61298086828701612900565b92505061298f60408501612920565b90509250925092565b6000602082840312156129aa57600080fd5b81356001600160401b038111156129c057600080fd5b8201601f810184136129d157600080fd5b6129e0848235602084016128a9565b949350505050565b60008060008060008060c08789031215612a0157600080fd5b8635612a0c816127e2565b95506020870135612a1c816127e2565b945060408701356001600160401b03811115612a3757600080fd5b612a4389828a01612900565b94505060608701359250612a5960808801612920565b9150612a6760a08801612920565b90509295509295509295565b600060208284031215612a8557600080fd5b813561113b816127e2565b600060c08284031215612aa257600080fd5b612aaa61280d565b90508135815260208201356020820152604082013560408201526060820135606082015260808201356001600160401b0380821115612ae857600080fd5b612af485838601612900565b608084015260a0840135915080821115612b0d57600080fd5b50612b1a84828501612900565b60a08301525092915050565b600060408284031215612b3857600080fd5b612b40612835565b9050813581526020808301356001600160401b0380821115612b6157600080fd5b818501915085601f830112612b7557600080fd5b813581811115612b8757612b876127f7565b8060051b9150612b98848301612879565b8181529183018401918481019088841115612bb257600080fd5b938501935b83851015612bd057843582529385019390850190612bb7565b808688015250505050505092915050565b600080600080600060a08688031215612bf957600080fd5b8535612c04816127e2565b94506020860135612c14816127e2565b935060408601356001600160401b0380821115612c3057600080fd5b612c3c89838a01612900565b9450606088013593506080880135915080821115612c5957600080fd5b9087019060a0828a031215612c6d57600080fd5b612c75612857565b82358152602083013582811115612c8b57600080fd5b612c978b828601612a90565b602083015250604083013582811115612caf57600080fd5b612cbb8b828601612b26565b604083015250606083013582811115612cd357600080fd5b612cdf8b828601612900565b606083015250608083013582811115612cf757600080fd5b612d038b828601612900565b6080830152508093505050509295509295909350565b805164ffffffffff8116811461293457600080fd5b600060208284031215612d4057600080fd5b61113b82612d19565b60005b83811015612d64578181015183820152602001612d4c565b83811115612d73576000848401525b50505050565b60008151808452612d91816020860160208601612d49565b601f01601f19169290920160200192915050565b6001600160a01b0385168152608060208201819052600090612dc990830186612d79565b905064ffffffffff8416604083015263ffffffff8316606083015295945050505050565b60208152600061113b6020830184612d79565b600060208284031215612e1257600080fd5b815161113b816127e2565b600060608284031215612e2f57600080fd5b604051606081018181106001600160401b0382111715612e5157612e516127f7565b60405282518152612e6460208401612d19565b6020820152612e7560408401612d19565b60408201529392505050565b6001600160a01b0385811682528416602082015263ffffffff8316604082015260806060820181905260009061156e90830184612d79565b60008251612ecb818460208701612d49565b9190910192915050565b60008451612ee7818460208901612d49565b60609490941b6bffffffffffffffffffffffff191691909301908152601481019190915260340192915050565b6001600160a01b03858116825284166020820152608060408201819052600090612f4090830185612d79565b905082606083015295945050505050565b60018060a01b03841681528260208201526060604082015260006122fc6060830184612d79565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b805182526020810151602083015260408101516040830152606081015160608301526000608082015160c0608085015261300060c0850182612d79565b905060a083015184820360a08601526122fc8282612d79565b60208152600061113b6020830184612fc3565b60006020828403121561303e57600080fd5b8151801515811461113b57600080fd5b838152600060206060818401526130686060840186612fc3565b83810360408501526040810185518252828601516040848401528181518084526060850191508583019450600093505b808410156130b85784518252938501936001939093019290850190613098565b509998505050505050505050565b600083516130d8818460208801612d49565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008282101561313b5761313b613113565b500390565b634e487b7160e01b600052602160045260246000fd5b6000821982111561316957613169613113565b500190565b600060001982141561318257613182613113565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600060ff8316806131b2576131b2613189565b8060ff84160691505092915050565b600060ff821660ff8416808210156131db576131db613113565b90039392505050565b60008160001904831182151516156131fe576131fe613113565b500290565b60006020828403121561321557600080fd5b5051919050565b60008261322b5761322b613189565b50049056fea264697066735822122063c7024ca7ded8cdabced3c0d4897e94132ae114a75718c668aa1bf77465918864736f6c63430008090033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101375760003560e01c80637738034c116100b8578063b1b1b2091161007c578063b1b1b20914610255578063c4d66de814610278578063c6b94ab01461028b578063cba4c652146102ae578063d9ce1901146102c1578063f2fde38b146102d457600080fd5b80637738034c1461021057806381ada46c146102185780638456cb591461022b5780638da5cb5b146102335780638ec6a68a1461024457600080fd5b8063461a4478116100ff578063461a4478146101cf5780635c975abb146101e25780636e296e45146101ed5780636f1c8d47146101f5578063715018a61461020857600080fd5b80630ecf2eea1461013c57806321d800ec14610151578063299ca478146101895780633dbb202b146101b45780633f4ba83a146101c7575b600080fd5b61014f61014a3660046127c9565b6102e7565b005b61017461015f3660046127c9565b60ca6020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b60005461019c906001600160a01b031681565b6040516001600160a01b039091168152602001610180565b61014f6101c2366004612939565b610332565b61014f61045c565b61019c6101dd366004612998565b61046e565b60655460ff16610174565b61019c6104f5565b61014f6102033660046129e8565b61056a565b61014f610704565b61014f610716565b61014f6102263660046127c9565b610778565b61014f6107c0565b6033546001600160a01b031661019c565b60cd546001600160a01b031661019c565b6101746102633660046127c9565b60cb6020526000908152604090205460ff1681565b61014f610286366004612a73565b6107c8565b6101746102993660046127c9565b60c96020526000908152604090205460ff1681565b61014f6102bc366004612a73565b6109a4565b61014f6102cf366004612be1565b6109ce565b61014f6102e2366004612a73565b610daa565b6102ef610e23565b600081815260c96020526040808220805460ff191660011790555182917ff52508d5339edf0d7e5060a416df98db067af561bdc60872d29c0439eaa13a0291a250565b600061036e6040518060400160405280601981526020017821b0b737b734b1b0b62a3930b739b0b1ba34b7b721b430b4b760391b81525061046e565b90506000816001600160a01b031663b8f770056040518163ffffffff1660e01b815260040160206040518083038186803b1580156103ab57600080fd5b505afa1580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190612d2e565b905060006103fa8633878564ffffffffff16610e7d565b905061040d83828663ffffffff16610eca565b856001600160a01b03167fcb0f7ffd78f9aee47a248fae8db181db6eee833039123e026dcbff529522e52a3387858860405161044c9493929190612da5565b60405180910390a2505050505050565b610464610e23565b61046c610f38565b565b6000805460405163bf40fac160e01b81526001600160a01b039091169063bf40fac19061049f908590600401612ded565b60206040518083038186803b1580156104b757600080fd5b505afa1580156104cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ef9190612e00565b92915050565b60cc546000906001600160a01b031661dead141561055a5760405162461bcd60e51b815260206004820152601f60248201527f78446f6d61696e4d65737361676553656e646572206973206e6f74207365740060448201526064015b60405180910390fd5b5060cc546001600160a01b031690565b60006105a66040518060400160405280601981526020017821b0b737b734b1b0b62a3930b739b0b1ba34b7b721b430b4b760391b81525061046e565b60405163153f8c5f60e11b8152600481018690529091506000906001600160a01b03831690632a7f18be9060240160606040518083038186803b1580156105ec57600080fd5b505afa158015610600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106249190612e1d565b9050600061063489898989610e7d565b9050600073111100000000000000000000000000000000111130016007602160991b01878460405160200161066c9493929190612e81565b604051602081830303815290604052805190602001209050826000015181146106e75760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520686173206e6f74206265656e20656e60448201526638bab2bab2b21760c91b6064820152608401610551565b6106f884838763ffffffff16610eca565b50505050505050505050565b61070c610e23565b61046c6000610f8a565b60cd546001600160a01b031633146107705760405162461bcd60e51b815260206004820181905260248201527f6d73672e73656e6465722073686f756c652062652070617573656f776e65722e6044820152606401610551565b61046c610fdc565b610780610e23565b600081815260c96020526040808220805460ff191690555182917f52c8a2680a9f4cc0ad0bf88f32096eadbebf0646ea611d93a0ce6a29a024040591a250565b610770610e23565b600054600160a81b900460ff16158080156107f057506000546001600160a01b90910460ff16105b806108115750303b1580156108115750600054600160a01b900460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610551565b6000805460ff60a01b1916600160a01b17905580156108a1576000805460ff60a81b1916600160a81b1790555b6000546001600160a01b03161561090d5760405162461bcd60e51b815260206004820152602a60248201527f4c3143726f7373446f6d61696e4d657373656e67657220616c72656164792069604482015269373a34b0b634bd32b21760b11b6064820152608401610551565b600080546001600160a01b0384166001600160a01b03199182161790915560cc805490911661dead179055610940611019565b610948611042565b610950611074565b6109586110a9565b80156109a0576000805460ff60a81b19169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6109ac610e23565b60cd80546001600160a01b0319166001600160a01b0392909216919091179055565b60026097541415610a215760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610551565b6002609755610a2e6110d9565b6000610a3c86868686610e7d565b9050610a48818361111f565b1515600114610aa95760405162461bcd60e51b815260206004820152602760248201527f50726f7669646564206d65737361676520636f756c64206e6f742062652076656044820152663934b334b2b21760c91b6064820152608401610551565b8051602080830191909120600081815260cb90925260409091205460ff1615610b285760405162461bcd60e51b815260206004820152602b60248201527f50726f7669646564206d6573736167652068617320616c72656164792062656560448201526a37103932b1b2b4bb32b21760a91b6064820152608401610551565b600081815260c9602052604090205460ff1615610b925760405162461bcd60e51b815260206004820152602260248201527f50726f7669646564206d65737361676520686173206265656e20626c6f636b65604482015261321760f11b6064820152608401610551565b610bcc6040518060400160405280601981526020017821b0b737b734b1b0b62a3930b739b0b1ba34b7b721b430b4b760391b81525061046e565b6001600160a01b0316876001600160a01b03161415610c495760405162461bcd60e51b815260206004820152603360248201527f43616e6e6f742073656e64204c322d3e4c31206d6573736167657320746f204c604482015272189039bcb9ba32b69031b7b73a3930b1ba399760691b6064820152608401610551565b60cc80546001600160a01b0319166001600160a01b0388811691909117909155604051600091891690610c7d908890612eb9565b6000604051808303816000865af19150503d8060008114610cba576040519150601f19603f3d011682016040523d82523d6000602084013e610cbf565b606091505b505060cc80546001600160a01b03191661dead179055905080151560011415610d2757600082815260cb6020526040808220805460ff191660011790555183917f4641df4a962071e12719d8c8c8e5ac7fc4d97b927346a3d7a335b1f7517e133c91a2610d53565b60405182907f99d0e048484baa1b1540b1367cb128acd7ab2946d1ed91ec10e3c85e4bf51b8f90600090a25b6000833343604051602001610d6a93929190612ed5565b60408051601f198184030181529181528151602092830120600090815260ca9092529020805460ff19166001908117909155609755505050505050505050565b610db2610e23565b6001600160a01b038116610e175760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610551565b610e2081610f8a565b50565b6033546001600160a01b0316331461046c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610551565b606084848484604051602401610e969493929190612f14565b60408051601f198184030181529190526020810180516001600160e01b031663cbd4ece960e01b1790529050949350505050565b60405163037f703f60e51b81526001600160a01b03841690636fee07e090610f01906007602160991b019085908790600401612f51565b600060405180830381600087803b158015610f1b57600080fd5b505af1158015610f2f573d6000803e3d6000fd5b50505050505050565b610f40611142565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b610fe46110d9565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f6d3390565b600054600160a81b900460ff1661046c5760405162461bcd60e51b815260040161055190612f78565b600054600160a81b900460ff1661106b5760405162461bcd60e51b815260040161055190612f78565b61046c33610f8a565b600054600160a81b900460ff1661109d5760405162461bcd60e51b815260040161055190612f78565b6065805460ff19169055565b600054600160a81b900460ff166110d25760405162461bcd60e51b815260040161055190612f78565b6001609755565b60655460ff161561046c5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610551565b600061112a8261118b565b801561113b575061113b83836112d8565b9392505050565b60655460ff1661046c5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610551565b6000806111c36040518060400160405280601481526020017329ba30ba32a1b7b6b6b4ba36b2b73a21b430b4b760611b81525061046e565b602084015160405163011343b360e71b81529192506001600160a01b038316916389a1d980916111f591600401613019565b60206040518083038186803b15801561120d57600080fd5b505afa158015611221573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611245919061302c565b15801561113b575082516020840151604080860151905163b768bb1760e01b81526001600160a01b0385169363b768bb179361128893919290919060040161304e565b60206040518083038186803b1580156112a057600080fd5b505afa1580156112b4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b919061302c565b600080836007602160991b016040516020016112f59291906130c6565b60408051601f1981840301815282825280516020918201209083015260009082015260600160408051601f19818403018152908290528051602091820120602160f91b91830191909152915060009081906113699060340160408051601f1981840301815291905260608701518751611467565b90925090506001821515146113fc5760405162461bcd60e51b815260206004820152604d60248201527f4d6573736167652070617373696e67207072656465706c6f7920686173206e6f60448201527f74206265656e20696e697469616c697a6564206f7220696e76616c696420707260648201526c37b7b310383937bb34b232b21760991b608482015260a401610551565b600061140782611490565b905061145c8460405160200161141f91815260200190565b60408051601f1981840301815290829052600160f81b60208301529060210160405160208183030381529060405288608001518460400151611554565b979650505050505050565b60006060600061147686611578565b90506114838186866115aa565b9250925050935093915050565b6040805160808101825260008082526020820181905291810182905260608101829052906114bd83611685565b905060405180608001604052806114ed836000815181106114e0576114e06130fd565b60200260200101516116b8565b8152602001611508836001815181106114e0576114e06130fd565b815260200161153083600281518110611523576115236130fd565b60200260200101516116bf565b815260200161154b83600381518110611523576115236130fd565b90529392505050565b60008061156086611578565b905061156e818686866117c1565b9695505050505050565b6060818051906020012060405160200161159491815260200190565b6040516020818303038152906040529050919050565b6000606060006115b9856117f7565b905060008060006115cb848a896118f1565b815192955090935091501580806115df5750815b61162b5760405162461bcd60e51b815260206004820152601a60248201527f50726f76696465642070726f6f6620697320696e76616c69642e0000000000006044820152606401610551565b6000816116475760405180602001604052806000815250611673565b61167386611656600188613129565b81518110611666576116666130fd565b6020026020010151611d15565b919b919a509098505050505050505050565b6040805180820182526000808252602091820152815180830190925282518252808301908201526060906104ef90611d3f565b60006104ef825b60006021826000015111156117165760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610551565b600080600061172485611f2b565b91945092509050600081600181111561173f5761173f613140565b1461178c5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420524c5020627974657333322076616c75652e0000000000006044820152606401610551565b600083866020015161179e9190613156565b8051909150602084101561156e5760208490036101000a90049695505050505050565b60008060006117d18786866115aa565b9150915081801561145c575080516020808301919091208751918801919091201461145c565b6060600061180483611685565b9050600081516001600160401b03811115611821576118216127f7565b60405190808252806020026020018201604052801561186657816020015b604080518082019091526060808252602082015281526020019060019003908161183f5790505b50905060005b82518110156118e957600061189984838151811061188c5761188c6130fd565b6020026020010151612275565b905060405180604001604052808281526020016118b583611685565b8152508383815181106118ca576118ca6130fd565b60200260200101819052505080806118e19061316e565b91505061186c565b509392505050565b6000606081808061190187612305565b90506000869050600080611928604051806040016040528060608152602001606081525090565b60005b8c51811015611ced578c8181518110611946576119466130fd565b60200260200101519150828461195c9190613156565b9350611969600188613156565b9650836119c1578151805160209091012085146119bc5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840e4dedee840d0c2e6d607b1b6044820152606401610551565b611a7e565b815151602011611a23578151805160209091012085146119bc5760405162461bcd60e51b815260206004820152601b60248201527f496e76616c6964206c6172676520696e7465726e616c206861736800000000006044820152606401610551565b84611a31836000015161243f565b14611a7e5760405162461bcd60e51b815260206004820152601a60248201527f496e76616c696420696e7465726e616c206e6f646520686173680000000000006044820152606401610551565b611a8a60106001613156565b8260200151511415611b03578551841415611aa457611ced565b6000868581518110611ab857611ab86130fd565b602001015160f81c60f81b60f81c9050600083602001518260ff1681518110611ae357611ae36130fd565b60200260200101519050611af681612467565b9650600194505050611cdb565b60028260200151511415611c93576000611b1c8361249d565b9050600081600081518110611b3357611b336130fd565b016020015160f81c90506000611b4a60028361319f565b611b559060026131c1565b90506000611b66848360ff166124c1565b90506000611b748b8a6124c1565b90506000611b8283836124f7565b905060ff851660021480611b99575060ff85166003145b15611bd357808351148015611bae5750808251145b15611bc057611bbd818b613156565b99505b50600160ff1b9950611ced945050505050565b60ff85161580611be6575060ff85166001145b15611c3c5782518114611c065750600160ff1b9950611ced945050505050565b611c2d8860200151600181518110611c2057611c206130fd565b6020026020010151612467565b9a509750611cdb945050505050565b60405162461bcd60e51b815260206004820152602660248201527f52656365697665642061206e6f6465207769746820616e20756e6b6e6f776e206044820152650e0e4caccd2f60d31b6064820152608401610551565b60405162461bcd60e51b815260206004820152601d60248201527f526563656976656420616e20756e706172736561626c65206e6f64652e0000006044820152606401610551565b80611ce58161316e565b91505061192b565b50600160ff1b841486611d0087866124c1565b909e909d50909b509950505050505050505050565b602081015180516060916104ef91611d2f90600190613129565b8151811061188c5761188c6130fd565b6060600080611d4d84611f2b565b91935090915060019050816001811115611d6957611d69613140565b14611db65760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c50206c6973742076616c75652e0000000000000000006044820152606401610551565b6040805160208082526104208201909252600091816020015b6040805180820190915260008082526020820152815260200190600190039081611dcf5790505090506000835b8651811015611f205760208210611e685760405162461bcd60e51b815260206004820152602a60248201527f50726f766964656420524c50206c6973742065786365656473206d6178206c6960448201526939ba103632b733ba341760b11b6064820152608401610551565b600080611ea56040518060400160405280858c60000151611e899190613129565b8152602001858c60200151611e9e9190613156565b9052611f2b565b509150915060405180604001604052808383611ec19190613156565b8152602001848b60200151611ed69190613156565b815250858581518110611eeb57611eeb6130fd565b6020908102919091010152611f01600185613156565b9350611f0d8183613156565b611f179084613156565b92505050611dfc565b508152949350505050565b600080600080846000015111611f835760405162461bcd60e51b815260206004820152601860248201527f524c50206974656d2063616e6e6f74206265206e756c6c2e00000000000000006044820152606401610551565b6020840151805160001a607f8111611fa857600060016000945094509450505061226e565b60b78111612024576000611fbd608083613129565b9050808760000151116120125760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420524c502073686f727420737472696e672e000000000000006044820152606401610551565b6001955093506000925061226e915050565b60bf811161211357600061203960b783613129565b90508087600001511161208e5760405162461bcd60e51b815260206004820152601f60248201527f496e76616c696420524c50206c6f6e6720737472696e67206c656e6774682e006044820152606401610551565b600183015160208290036101000a90046120a88183613156565b8851116120f75760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c50206c6f6e6720737472696e672e00000000000000006044820152606401610551565b612102826001613156565b965094506000935061226e92505050565b60f7811161218e57600061212860c083613129565b90508087600001511161217d5760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420524c502073686f7274206c6973742e0000000000000000006044820152606401610551565b60019550935084925061226e915050565b600061219b60f783613129565b9050808760000151116121f05760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420524c50206c6f6e67206c697374206c656e6774682e0000006044820152606401610551565b600183015160208290036101000a900461220a8183613156565b8851116122525760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b210292628103637b733903634b9ba1760511b6044820152606401610551565b61225d826001613156565b965094506001935061226e92505050565b9193909250565b6060600080600061228585611f2b565b9194509250905060008160018111156122a0576122a0613140565b146122ed5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420524c502062797465732076616c75652e00000000000000006044820152606401610551565b6122fc85602001518484612573565b95945050505050565b606060008251600261231791906131e4565b6001600160401b0381111561232e5761232e6127f7565b6040519080825280601f01601f191660200182016040528015612358576020820181803683370190505b50905060005b835181101561243857600484828151811061237b5761237b6130fd565b01602001516001600160f81b031916901c826123988360026131e4565b815181106123a8576123a86130fd565b60200101906001600160f81b031916908160001a90535060108482815181106123d3576123d36130fd565b01602001516123e5919060f81c61319f565b60f81b826123f48360026131e4565b6123ff906001613156565b8151811061240f5761240f6130fd565b60200101906001600160f81b031916908160001a905350806124308161316e565b91505061235e565b5092915050565b600060208251101561245357506020015190565b818060200190518101906104ef9190613203565b600060606020836000015110156124885761248183612651565b9050612494565b61249183612275565b90505b61113b8161243f565b60606104ef6124bc836020015160008151811061188c5761188c6130fd565b612305565b6060825182106124e057506040805160208101909152600081526104ef565b61113b83838486516124f29190613129565b61265c565b6000805b80845111801561250b5750808351115b801561255c5750828181518110612524576125246130fd565b602001015160f81c60f81b6001600160f81b03191684828151811061254b5761254b6130fd565b01602001516001600160f81b031916145b1561113b578061256b8161316e565b9150506124fb565b60606000826001600160401b0381111561258f5761258f6127f7565b6040519080825280601f01601f1916602001820160405280156125b9576020820181803683370190505b5090508051600014156125cd57905061113b565b60006125d98587613156565b90506020820160005b6125ed60208761321c565b8110156126245782518252612603602084613156565b9250612610602083613156565b91508061261c8161316e565b9150506125e2565b5060006001602087066020036101000a039050808251168119845116178252839450505050509392505050565b60606104ef826127b3565b60608161266a81601f613156565b10156126a95760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610551565b826126b48382613156565b10156126f35760405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606401610551565b6126fd8284613156565b845110156127415760405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606401610551565b60608215801561276057604051915060008252602082016040526127aa565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015612799578051835260209283019201612781565b5050858452601f01601f1916604052505b50949350505050565b60606104ef826020015160008460000151612573565b6000602082840312156127db57600080fd5b5035919050565b6001600160a01b0381168114610e2057600080fd5b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b038111828210171561282f5761282f6127f7565b60405290565b604080519081016001600160401b038111828210171561282f5761282f6127f7565b60405160a081016001600160401b038111828210171561282f5761282f6127f7565b604051601f8201601f191681016001600160401b03811182821017156128a1576128a16127f7565b604052919050565b60006001600160401b038311156128c2576128c26127f7565b6128d5601f8401601f1916602001612879565b90508281528383830111156128e957600080fd5b828260208301376000602084830101529392505050565b600082601f83011261291157600080fd5b61113b838335602085016128a9565b803563ffffffff8116811461293457600080fd5b919050565b60008060006060848603121561294e57600080fd5b8335612959816127e2565b925060208401356001600160401b0381111561297457600080fd5b61298086828701612900565b92505061298f60408501612920565b90509250925092565b6000602082840312156129aa57600080fd5b81356001600160401b038111156129c057600080fd5b8201601f810184136129d157600080fd5b6129e0848235602084016128a9565b949350505050565b60008060008060008060c08789031215612a0157600080fd5b8635612a0c816127e2565b95506020870135612a1c816127e2565b945060408701356001600160401b03811115612a3757600080fd5b612a4389828a01612900565b94505060608701359250612a5960808801612920565b9150612a6760a08801612920565b90509295509295509295565b600060208284031215612a8557600080fd5b813561113b816127e2565b600060c08284031215612aa257600080fd5b612aaa61280d565b90508135815260208201356020820152604082013560408201526060820135606082015260808201356001600160401b0380821115612ae857600080fd5b612af485838601612900565b608084015260a0840135915080821115612b0d57600080fd5b50612b1a84828501612900565b60a08301525092915050565b600060408284031215612b3857600080fd5b612b40612835565b9050813581526020808301356001600160401b0380821115612b6157600080fd5b818501915085601f830112612b7557600080fd5b813581811115612b8757612b876127f7565b8060051b9150612b98848301612879565b8181529183018401918481019088841115612bb257600080fd5b938501935b83851015612bd057843582529385019390850190612bb7565b808688015250505050505092915050565b600080600080600060a08688031215612bf957600080fd5b8535612c04816127e2565b94506020860135612c14816127e2565b935060408601356001600160401b0380821115612c3057600080fd5b612c3c89838a01612900565b9450606088013593506080880135915080821115612c5957600080fd5b9087019060a0828a031215612c6d57600080fd5b612c75612857565b82358152602083013582811115612c8b57600080fd5b612c978b828601612a90565b602083015250604083013582811115612caf57600080fd5b612cbb8b828601612b26565b604083015250606083013582811115612cd357600080fd5b612cdf8b828601612900565b606083015250608083013582811115612cf757600080fd5b612d038b828601612900565b6080830152508093505050509295509295909350565b805164ffffffffff8116811461293457600080fd5b600060208284031215612d4057600080fd5b61113b82612d19565b60005b83811015612d64578181015183820152602001612d4c565b83811115612d73576000848401525b50505050565b60008151808452612d91816020860160208601612d49565b601f01601f19169290920160200192915050565b6001600160a01b0385168152608060208201819052600090612dc990830186612d79565b905064ffffffffff8416604083015263ffffffff8316606083015295945050505050565b60208152600061113b6020830184612d79565b600060208284031215612e1257600080fd5b815161113b816127e2565b600060608284031215612e2f57600080fd5b604051606081018181106001600160401b0382111715612e5157612e516127f7565b60405282518152612e6460208401612d19565b6020820152612e7560408401612d19565b60408201529392505050565b6001600160a01b0385811682528416602082015263ffffffff8316604082015260806060820181905260009061156e90830184612d79565b60008251612ecb818460208701612d49565b9190910192915050565b60008451612ee7818460208901612d49565b60609490941b6bffffffffffffffffffffffff191691909301908152601481019190915260340192915050565b6001600160a01b03858116825284166020820152608060408201819052600090612f4090830185612d79565b905082606083015295945050505050565b60018060a01b03841681528260208201526060604082015260006122fc6060830184612d79565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b805182526020810151602083015260408101516040830152606081015160608301526000608082015160c0608085015261300060c0850182612d79565b905060a083015184820360a08601526122fc8282612d79565b60208152600061113b6020830184612fc3565b60006020828403121561303e57600080fd5b8151801515811461113b57600080fd5b838152600060206060818401526130686060840186612fc3565b83810360408501526040810185518252828601516040848401528181518084526060850191508583019450600093505b808410156130b85784518252938501936001939093019290850190613098565b509998505050505050505050565b600083516130d8818460208801612d49565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008282101561313b5761313b613113565b500390565b634e487b7160e01b600052602160045260246000fd5b6000821982111561316957613169613113565b500190565b600060001982141561318257613182613113565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600060ff8316806131b2576131b2613189565b8060ff84160691505092915050565b600060ff821660ff8416808210156131db576131db613113565b90039392505050565b60008160001904831182151516156131fe576131fe613113565b500290565b60006020828403121561321557600080fd5b5051919050565b60008261322b5761322b613189565b50049056fea264697066735822122063c7024ca7ded8cdabced3c0d4897e94132ae114a75718c668aa1bf77465918864736f6c63430008090033
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.