Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 14218252 | 956 days ago | IN | 0 ETH | 0.3870448 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ATokenRootChainManager
Compiler Version
v0.6.6+commit.6c089d02
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.6.6; /** * aToken bridge to Matic Network * Author: Nick Mudge <[email protected]> * Modified from Matics ERC20 bridge: https://github.com/maticnetwork/pos-portal */ import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; import {ICheckpointManager} from "../ICheckpointManager.sol"; import {RLPReader} from "../../lib/RLPReader.sol"; import {ExitPayloadReader} from "../../lib/ExitPayloadReader.sol"; import {MerklePatriciaProof} from "../../lib/MerklePatriciaProof.sol"; import {Merkle} from "../../lib/Merkle.sol"; import {NativeMetaTransaction} from "../../common/NativeMetaTransaction.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ContextMixin} from "../../common/ContextMixin.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import {IStateSender} from "../StateSender/IStateSender.sol"; import {ICheckpointManager} from "../ICheckpointManager.sol"; interface ILendingPool { function getReserveNormalizedIncome(address _asset) external view returns (uint256); } interface IAToken { function POOL() external view returns (ILendingPool); function UNDERLYING_ASSET_ADDRESS() external view returns (address); } interface IERC20Meta { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); } struct AppStorage { mapping(address => address) rootToChildToken; mapping(address => address) childToRootToken; mapping(bytes32 => bool) processedExits; bool inited; IStateSender stateSender; ICheckpointManager checkpointManager; address childChainManagerAddress; bytes32 childTokenBytecodeHash; address owner; address mapper; } contract ATokenRootChainManager is ICheckpointManager, NativeMetaTransaction, ContextMixin { using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; using ExitPayloadReader for bytes; using ExitPayloadReader for ExitPayloadReader.ExitPayload; using ExitPayloadReader for ExitPayloadReader.Log; using ExitPayloadReader for ExitPayloadReader.Receipt; using Merkle for bytes32; using SafeMath for uint256; using SafeERC20 for IERC20; AppStorage s; // maybe DEPOSIT and MAP_TOKEN can be reduced to bytes4 bytes32 public constant DEPOSIT = keccak256("DEPOSIT"); bytes32 public constant MAP_TOKEN = keccak256("MAP_TOKEN"); bytes32 public constant MAPPER_ROLE = keccak256("MAPPER_ROLE"); uint256 internal constant P27 = 1e27; uint256 internal constant HALF_P27 = P27 / 2; bytes32 public constant TRANSFER_EVENT_SIG = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; event TokenMapped(address indexed rootToken, address indexed childToken, bytes32 indexed tokenType); event LockedERC20(address indexed depositor, address indexed depositReceiver, address indexed rootToken, uint256 amount); /** * @notice Deposit ether by directly sending to the contract * The account sending ether receives WETH on child chain */ receive() external payable { revert("Cannot send ETH over aToken bridge"); } function initialize( address _owner, address _stateSender, address _checkpointManager, address _childChainManagerAddress, bytes32 _childTokenBytecodeHash ) external { require(!s.inited, "already inited"); s.inited = true; _initializeEIP712("ATokenRootChainManager"); s.owner = _owner; s.mapper = _owner; s.stateSender = IStateSender(_stateSender); s.checkpointManager = ICheckpointManager(_checkpointManager); s.childChainManagerAddress = _childChainManagerAddress; s.childTokenBytecodeHash = _childTokenBytecodeHash; } function rootToChildToken(address _rootToken) external view returns (address) { return s.rootToChildToken[_rootToken]; } function childToRootToken(address _childToken) external view returns (address) { return s.childToRootToken[_childToken]; } function mapper() external view returns (address) { return s.mapper; } function stateSender() external view returns (address) { return address(s.stateSender); } // Old function here so as to not break existing functionality function stateSenderAddress() external view returns (address) { return address(s.stateSender); } function owner() external view returns (address) { return s.owner; } modifier onlyOwner() { require(msgSender() == s.owner, "Is not owner"); _; } modifier onlyMapper() { address sender = msgSender(); require(sender == s.mapper || sender == s.owner, "Is not mapper"); _; } modifier onlyStateSender() { require(msgSender() == address(s.stateSender), "Is not state sender"); _; } function processedExits(bytes32 _exitHash) external view returns (bool) { return s.processedExits[_exitHash]; } /** * @notice Set the state sender, callable only by admins * @dev This should be the state sender from plasma contracts * It is used to send bytes from root to child chain * @param newStateSender address of state sender contract */ function setStateSender(address newStateSender) external onlyOwner { require(newStateSender != address(0), "RootChainManager: BAD_NEW_STATE_SENDER"); s.stateSender = IStateSender(newStateSender); } /** * @notice Set the checkpoint manager, callable only by admins * @dev This should be the plasma contract responsible for keeping track of checkpoints * @param newCheckpointManager address of checkpoint manager contract */ function setCheckpointManager(address newCheckpointManager) external onlyOwner { require(newCheckpointManager != address(0), "RootChainManager: BAD_NEW_CHECKPOINT_MANAGER"); s.checkpointManager = ICheckpointManager(newCheckpointManager); } /** * @notice Get the address of contract set as checkpoint manager * @return The address of checkpoint manager contract */ function checkpointManagerAddress() external view returns (address) { return address(s.checkpointManager); } event SetOwner(address indexed _previousOwner, address indexed _newOwner); function setOwner(address _newOwner) external onlyOwner { emit SetOwner(s.owner, _newOwner); s.owner = _newOwner; } event SetMapper(address indexed _previousMapper, address indexed _newMapper); function setMapper(address _newMapper) external onlyOwner { emit SetMapper(s.mapper, _newMapper); s.mapper = _newMapper; } /** * @notice Set the child chain manager, callable only by admins * @dev This should be the contract responsible to receive deposit bytes on child chain * @param newChildChainManager address of child chain manager contract * @param newChildTokenBytecodeHash hash of bytecode used to create child token */ function setChildChainManagerAddressAndChildTokenBytecodeHash(address newChildChainManager, bytes32 newChildTokenBytecodeHash) external onlyOwner { require(newChildChainManager != address(0x0), "ATokenRootChainManager: INVALID_CHILD_CHAIN_ADDRESS"); s.childChainManagerAddress = newChildChainManager; s.childTokenBytecodeHash = newChildTokenBytecodeHash; } /** * @notice Set the child chain manager, callable only by admins * @dev This should be the contract responsible to receive deposit bytes on child chain * @param newChildChainManager address of child chain manager contract */ function setChildChainManagerAddress(address newChildChainManager) external onlyOwner { require(newChildChainManager != address(0x0), "ATokenRootChainManager: INVALID_CHILD_CHAIN_ADDRESS"); s.childChainManagerAddress = newChildChainManager; } /** * @notice Set the child bytecode hash * @dev This is used by a create2 call to precalculate the child token address * @param newChildTokenBytecodeHash address of child chain manager contract */ function setChildTokenBytecodeHash(bytes32 newChildTokenBytecodeHash) external onlyOwner { s.childTokenBytecodeHash = newChildTokenBytecodeHash; } function childTokenAddress(address rootToken) public view returns (address childToken_) { // precompute childToken address for mapping childToken_ = address( uint160( uint256( keccak256( abi.encodePacked( bytes1(0xff), s.childChainManagerAddress, // contract creating address bytes32(bytes20(rootToken)), // salt s.childTokenBytecodeHash // bytecode hash ) ) ) ) ); } /** * @notice Map a token to enable its movement via the PoS Portal, callable only by mappers * @param rootToken address of token on root chain */ function mapToken(address rootToken) external onlyMapper { // explicit check if token is already mapped to avoid accidental remaps require(s.rootToChildToken[rootToken] == address(0), "ATokenRootChainManager: ALREADY_MAPPED"); address childToken = childTokenAddress(rootToken); _mapToken(rootToken, childToken); } /** * @notice Remap a token that has already been mapped, properly cleans up old mapping * Callable only by ADMIN * @param rootToken address of token on root chain */ function remapToken(address rootToken) external onlyOwner { address childToken = childTokenAddress(rootToken); // cleanup old mapping address oldChildToken = s.rootToChildToken[rootToken]; require(childToken != oldChildToken, "ATokenRootChainManager: Child token is the same"); address oldRootToken = s.childToRootToken[childToken]; if (s.rootToChildToken[oldRootToken] != address(0)) { s.rootToChildToken[oldRootToken] = address(0); } if (s.childToRootToken[oldChildToken] != address(0)) { s.childToRootToken[oldChildToken] = address(0); } _mapToken(rootToken, childToken); } function _mapToken(address rootToken, address childToken) private { s.rootToChildToken[rootToken] = childToken; s.childToRootToken[childToken] = rootToken; emit TokenMapped(rootToken, childToken, 0x0); bytes memory syncData = abi.encode( rootToken, abi.encodePacked("Matic ", IERC20Meta(rootToken).name()), abi.encodePacked("m", IERC20Meta(rootToken).symbol()), IERC20Meta(rootToken).decimals() ); s.stateSender.syncState(s.childChainManagerAddress, abi.encode(MAP_TOKEN, syncData)); } /** * @notice Move tokens from root to child chain * @dev This mechanism supports arbitrary tokens as long as its predicate has been registered and the token is mapped * @param user address of account that should receive this deposit on child chain * @param rootToken address of token that is being deposited * @param depositData bytes data that is sent to predicate and child token contracts to handle deposit */ function depositFor( address user, address rootToken, bytes memory depositData ) public { require(s.rootToChildToken[rootToken] != address(0x0), "ATokenRootChainManager: TOKEN_NOT_MAPPED"); require(user != address(0), "ATokenRootChainManager: INVALID_USER"); uint256 aTokenValue = abi.decode(depositData, (uint256)); address depositor = msgSender(); emit LockedERC20(depositor, user, rootToken, aTokenValue); IERC20(rootToken).safeTransferFrom(depositor, address(this), aTokenValue); uint256 maTokenValue = getMATokenValue(rootToken, aTokenValue); // replace aTokenValue with maTokenValue in depositData // assembly increases start of bytes array and reduces the size by one uint256 uint256 depositDataLength = depositData.length; assembly { depositData := add(depositData, 32) mstore(depositData, sub(depositDataLength, 32)) } depositData = abi.encodePacked(maTokenValue, depositData); bytes memory syncData = abi.encode(user, rootToken, depositData); s.stateSender.syncState(s.childChainManagerAddress, abi.encode(DEPOSIT, syncData)); } /** * @dev Divides two 27 decimal percision values, rounding half up to the nearest decimal * @param a 27 decimal percision value * @param b 27 decimal percision value * @return The result of a/b, in 27 decimal percision value **/ function p27Div(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "p27 division by 0"); uint256 c = a * P27; require(a == c / P27, "p27 multiplication overflow"); uint256 bDividedByTwo = b / 2; c += bDividedByTwo; require(c >= bDividedByTwo, "p27 multiplication addition overflow"); return c / b; } /** * @dev Multiplies two 27 decimal percision values, rounding half up to the nearest decimal * @param a 27 decimal percision value * @param b 27 decimal percision value * @return The result of a*b, in 27 decimal percision value **/ function p27Mul(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a * b; if (c == 0) { return 0; } require(b == c / a, "p27 multiplication overflow"); c += HALF_P27; require(c >= HALF_P27, "p27 multiplication addition overflow"); return c / P27; } /** * @dev Converts aToken value to maToken value * @param _aTokenAddress aToken contract address * @param _aTokenValue aToken value to convert * @return maTokenValue_ The converted maToken value **/ function getMATokenValue(address _aTokenAddress, uint256 _aTokenValue) public view returns (uint256 maTokenValue_) { ILendingPool pool = IAToken(_aTokenAddress).POOL(); uint256 liquidityIndex = pool.getReserveNormalizedIncome(IAToken(_aTokenAddress).UNDERLYING_ASSET_ADDRESS()); maTokenValue_ = p27Div(_aTokenValue, liquidityIndex); } /** * @dev Converts maToken value to aToken value * @param _aTokenAddress aToken contract address * @param _maTokenValue maToken value to convert * @return aTokenValue_ The converted aToken value **/ function getATokenValue(address _aTokenAddress, uint256 _maTokenValue) public view returns (uint256 aTokenValue_) { ILendingPool pool = IAToken(_aTokenAddress).POOL(); uint256 liquidityIndex = pool.getReserveNormalizedIncome(IAToken(_aTokenAddress).UNDERLYING_ASSET_ADDRESS()); aTokenValue_ = p27Mul(_maTokenValue, liquidityIndex); } /** * @notice exit tokens by providing proof * @dev This function verifies if the transaction actually happened on child chain * the transaction log is then sent to token predicate to handle it accordingly * * @param inputData RLP encoded data of the reference tx containing following list of fields * 0 - headerNumber - Checkpoint header block number containing the reference tx * 1 - blockProof - Proof that the block header (in the child chain) is a leaf in the submitted merkle root * 2 - blockNumber - Block number containing the reference tx on child chain * 3 - blockTime - Reference tx block time * 4 - txRoot - Transactions root of block * 5 - receiptRoot - Receipts root of block * 6 - receipt - Receipt of the reference transaction * 7 - receiptProof - Merkle proof of the reference receipt * 8 - branchMask - 32 bits denoting the path of receipt in merkle tree * 9 - receiptLogIndex - Log Index to read from the receipt */ function exit(bytes calldata inputData) external { ExitPayloadReader.ExitPayload memory payload = inputData.toExitPayload(); bytes memory branchMaskBytes = payload.getBranchMaskAsBytes(); // checking if exit has already been processed // unique exit is identified using hash of (blockNumber, branchMask, receiptLogIndex) bytes32 exitHash = keccak256( abi.encodePacked( payload.getBlockNumber(), // first 2 nibbles are dropped while generating nibble array // this allows branch masks that are valid but bypass exitHash check (changing first 2 nibbles only) // so converting to nibble array and then hashing it MerklePatriciaProof._getNibbleArray(branchMaskBytes), payload.getReceiptLogIndex() ) ); require(s.processedExits[exitHash] == false, "ATokenRootChainManager: EXIT_ALREADY_PROCESSED"); s.processedExits[exitHash] = true; ExitPayloadReader.Receipt memory receipt = payload.getReceipt(); ExitPayloadReader.Log memory log = receipt.getLog(); // log should be emmited only by the child token address rootToken = s.childToRootToken[log.getEmitter()]; require(rootToken != address(0), "ATokenRootChainManager: TOKEN_NOT_MAPPED"); // branch mask can be maximum 32 bits require( payload.getBranchMaskAsUint() & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000 == 0, "ATokenRootChainManager: INVALID_BRANCH_MASK" ); // verify receipt inclusion require( MerklePatriciaProof.verify( receipt.toBytes(), branchMaskBytes, payload.getReceiptProof(), payload.getReceiptRoot() ), "ATokenRootChainManager: INVALID_PROOF" ); // verify checkpoint inclusion _checkBlockMembershipInCheckpoint( payload.getBlockNumber(), payload.getBlockTime(), payload.getTxRoot(), payload.getReceiptRoot(), payload.getHeaderNumber(), payload.getBlockProof() ); exitTokens(msgSender(), rootToken, log.toRlpBytes()); } function exitTokens( address, address rootToken, bytes memory log ) private { RLPReader.RLPItem[] memory logRLPList = log.toRlpItem().toList(); RLPReader.RLPItem[] memory logTopicRLPList = logRLPList[1].toList(); // topics require( bytes32(logTopicRLPList[0].toUint()) == TRANSFER_EVENT_SIG, // topic0 is event sig "ATokenRootChainManager: INVALID_SIGNATURE" ); address withdrawer = address(logTopicRLPList[1].toUint()); // topic1 is from address require( address(logTopicRLPList[2].toUint()) == address(0), // topic2 is to address "ATokenRootChainManager: INVALID_RECEIVER" ); uint256 maTokenValue = logRLPList[2].toUint(); // log data field uint256 aTokenValue = getATokenValue(rootToken, maTokenValue); IERC20(rootToken).safeTransfer(withdrawer, aTokenValue); } function _checkBlockMembershipInCheckpoint( uint256 blockNumber, uint256 blockTime, bytes32 txRoot, bytes32 receiptRoot, uint256 headerNumber, bytes memory blockProof ) private view returns (uint256) { (bytes32 headerRoot, uint256 startBlock, , uint256 createdAt, ) = s.checkpointManager.headerBlocks(headerNumber); require( keccak256(abi.encodePacked(blockNumber, blockTime, txRoot, receiptRoot)).checkMembership( blockNumber.sub(startBlock), headerRoot, blockProof ), "ATokenRootChainManager: INVALID_HEADER" ); return createdAt; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
pragma solidity 0.6.6; contract ICheckpointManager { struct HeaderBlock { bytes32 root; uint256 start; uint256 end; uint256 createdAt; address proposer; } /** * @notice mapping of checkpoint header numbers to block details * @dev These checkpoints are submited by plasma contracts */ mapping(uint256 => HeaderBlock) public headerBlocks; }
/* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns * https://github.com/hamdiallam/Solidity-RLP/blob/e681e25a376dbd5426b509380bc03446f05d0f97/contracts/RLPReader.sol */ pragma solidity 0.6.6; library RLPReader { uint8 constant STRING_SHORT_START = 0x80; uint8 constant STRING_LONG_START = 0xb8; uint8 constant LIST_SHORT_START = 0xc0; uint8 constant LIST_LONG_START = 0xf8; uint8 constant WORD_SIZE = 32; struct RLPItem { uint len; uint memPtr; } struct Iterator { RLPItem item; // Item that's being iterated over. uint nextPtr; // Position of the next item in the list. } /* * @dev Returns the next element in the iteration. Reverts if it has not next element. * @param self The iterator. * @return The next element in the iteration. */ function next(Iterator memory self) internal pure returns (RLPItem memory) { require(hasNext(self)); uint ptr = self.nextPtr; uint itemLength = _itemLength(ptr); self.nextPtr = ptr + itemLength; return RLPItem(itemLength, ptr); } /* * @dev Returns true if the iteration has more elements. * @param self The iterator. * @return true if the iteration has more elements. */ function hasNext(Iterator memory self) internal pure returns (bool) { RLPItem memory item = self.item; return self.nextPtr < item.memPtr + item.len; } /* * @param item RLP encoded bytes */ function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { uint memPtr; assembly { memPtr := add(item, 0x20) } return RLPItem(item.length, memPtr); } /* * @dev Create an iterator. Reverts if item is not a list. * @param self The RLP item. * @return An 'Iterator' over the item. */ function iterator(RLPItem memory self) internal pure returns (Iterator memory) { require(isList(self)); uint ptr = self.memPtr + _payloadOffset(self.memPtr); return Iterator(self, ptr); } /* * @param the RLP item. */ function rlpLen(RLPItem memory item) internal pure returns (uint) { return item.len; } /* * @param the RLP item. * @return (memPtr, len) pair: location of the item's payload in memory. */ function payloadLocation(RLPItem memory item) internal pure returns (uint, uint) { uint offset = _payloadOffset(item.memPtr); uint memPtr = item.memPtr + offset; uint len = item.len - offset; // data length return (memPtr, len); } /* * @param the RLP item. */ function payloadLen(RLPItem memory item) internal pure returns (uint) { (, uint len) = payloadLocation(item); return len; } /* * @param the RLP item containing the encoded list. */ function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { require(isList(item)); uint items = numItems(item); RLPItem[] memory result = new RLPItem[](items); uint memPtr = item.memPtr + _payloadOffset(item.memPtr); uint dataLen; for (uint i = 0; i < items; i++) { dataLen = _itemLength(memPtr); result[i] = RLPItem(dataLen, memPtr); memPtr = memPtr + dataLen; } return result; } // @return indicator whether encoded payload is a list. negate this function call for isData. function isList(RLPItem memory item) internal pure returns (bool) { if (item.len == 0) return false; uint8 byte0; uint memPtr = item.memPtr; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < LIST_SHORT_START) return false; return true; } /* * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. * @return keccak256 hash of RLP encoded bytes. */ function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { uint256 ptr = item.memPtr; uint256 len = item.len; bytes32 result; assembly { result := keccak256(ptr, len) } return result; } /* * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. * @return keccak256 hash of the item payload. */ function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { (uint memPtr, uint len) = payloadLocation(item); bytes32 result; assembly { result := keccak256(memPtr, len) } return result; } /** RLPItem conversions into data types **/ // @returns raw rlp encoding in bytes function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { bytes memory result = new bytes(item.len); if (result.length == 0) return result; uint ptr; assembly { ptr := add(0x20, result) } copy(item.memPtr, ptr, item.len); return result; } // any non-zero byte except "0x80" is considered true function toBoolean(RLPItem memory item) internal pure returns (bool) { require(item.len == 1); uint result; uint memPtr = item.memPtr; assembly { result := byte(0, mload(memPtr)) } // SEE Github Issue #5. // Summary: Most commonly used RLP libraries (i.e Geth) will encode // "0" as "0x80" instead of as "0". We handle this edge case explicitly // here. if (result == 0 || result == STRING_SHORT_START) { return false; } else { return true; } } function toAddress(RLPItem memory item) internal pure returns (address) { // 1 byte for the length prefix require(item.len == 21); return address(toUint(item)); } function toUint(RLPItem memory item) internal pure returns (uint) { require(item.len > 0 && item.len <= 33); (uint memPtr, uint len) = payloadLocation(item); uint result; assembly { result := mload(memPtr) // shfit to the correct location if neccesary if lt(len, 32) { result := div(result, exp(256, sub(32, len))) } } return result; } // enforces 32 byte length function toUintStrict(RLPItem memory item) internal pure returns (uint) { // one byte prefix require(item.len == 33); uint result; uint memPtr = item.memPtr + 1; assembly { result := mload(memPtr) } return result; } function toBytes(RLPItem memory item) internal pure returns (bytes memory) { require(item.len > 0); (uint memPtr, uint len) = payloadLocation(item); bytes memory result = new bytes(len); uint destPtr; assembly { destPtr := add(0x20, result) } copy(memPtr, destPtr, len); return result; } /* * Private Helpers */ // @return number of payload items inside an encoded list. function numItems(RLPItem memory item) private pure returns (uint) { if (item.len == 0) return 0; uint count = 0; uint currPtr = item.memPtr + _payloadOffset(item.memPtr); uint endPtr = item.memPtr + item.len; while (currPtr < endPtr) { currPtr = currPtr + _itemLength(currPtr); // skip over an item count++; } return count; } // @return entire rlp item byte length function _itemLength(uint memPtr) private pure returns (uint) { uint itemLen; uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) itemLen = 1; else if (byte0 < STRING_LONG_START) itemLen = byte0 - STRING_SHORT_START + 1; else if (byte0 < LIST_SHORT_START) { assembly { let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is memPtr := add(memPtr, 1) // skip over the first byte /* 32 byte word size */ let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len itemLen := add(dataLen, add(byteLen, 1)) } } else if (byte0 < LIST_LONG_START) { itemLen = byte0 - LIST_SHORT_START + 1; } else { assembly { let byteLen := sub(byte0, 0xf7) memPtr := add(memPtr, 1) let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length itemLen := add(dataLen, add(byteLen, 1)) } } return itemLen; } // @return number of bytes until the data function _payloadOffset(uint memPtr) private pure returns (uint) { uint byte0; assembly { byte0 := byte(0, mload(memPtr)) } if (byte0 < STRING_SHORT_START) return 0; else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) return 1; else if (byte0 < LIST_SHORT_START) // being explicit return byte0 - (STRING_LONG_START - 1) + 1; else return byte0 - (LIST_LONG_START - 1) + 1; } /* * @param src Pointer to source * @param dest Pointer to destination * @param len Amount of memory to copy from the source */ function copy(uint src, uint dest, uint len) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } if (len > 0) { // left over bytes. Mask is used to remove unwanted bytes from the word uint mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } } }
pragma solidity 0.6.6; import { RLPReader } from "./RLPReader.sol"; library ExitPayloadReader { using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; uint8 constant WORD_SIZE = 32; struct ExitPayload { RLPReader.RLPItem[] data; } struct Receipt { RLPReader.RLPItem[] data; bytes raw; uint256 logIndex; } struct Log { RLPReader.RLPItem data; RLPReader.RLPItem[] list; } struct LogTopics { RLPReader.RLPItem[] data; } // copy paste of private copy() from RLPReader to avoid changing of existing contracts function copy(uint src, uint dest, uint len) private pure { if (len == 0) return; // copy as many word sizes as possible for (; len >= WORD_SIZE; len -= WORD_SIZE) { assembly { mstore(dest, mload(src)) } src += WORD_SIZE; dest += WORD_SIZE; } // left over bytes. Mask is used to remove unwanted bytes from the word uint mask = 256 ** (WORD_SIZE - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) // zero out src let destpart := and(mload(dest), mask) // retrieve the bytes mstore(dest, or(destpart, srcpart)) } } function toExitPayload(bytes memory data) internal pure returns (ExitPayload memory) { RLPReader.RLPItem[] memory payloadData = data .toRlpItem() .toList(); return ExitPayload(payloadData); } function getHeaderNumber(ExitPayload memory payload) internal pure returns(uint256) { return payload.data[0].toUint(); } function getBlockProof(ExitPayload memory payload) internal pure returns(bytes memory) { return payload.data[1].toBytes(); } function getBlockNumber(ExitPayload memory payload) internal pure returns(uint256) { return payload.data[2].toUint(); } function getBlockTime(ExitPayload memory payload) internal pure returns(uint256) { return payload.data[3].toUint(); } function getTxRoot(ExitPayload memory payload) internal pure returns(bytes32) { return bytes32(payload.data[4].toUint()); } function getReceiptRoot(ExitPayload memory payload) internal pure returns(bytes32) { return bytes32(payload.data[5].toUint()); } function getReceipt(ExitPayload memory payload) internal pure returns(Receipt memory receipt) { receipt.raw = payload.data[6].toBytes(); RLPReader.RLPItem memory receiptItem = receipt.raw.toRlpItem(); if (receiptItem.isList()) { // legacy tx receipt.data = receiptItem.toList(); } else { // pop first byte before parsting receipt bytes memory typedBytes = receipt.raw; bytes memory result = new bytes(typedBytes.length - 1); uint256 srcPtr; uint256 destPtr; assembly { srcPtr := add(33, typedBytes) destPtr := add(0x20, result) } copy(srcPtr, destPtr, result.length); receipt.data = result.toRlpItem().toList(); } receipt.logIndex = getReceiptLogIndex(payload); return receipt; } function getReceiptProof(ExitPayload memory payload) internal pure returns(bytes memory) { return payload.data[7].toBytes(); } function getBranchMaskAsBytes(ExitPayload memory payload) internal pure returns(bytes memory) { return payload.data[8].toBytes(); } function getBranchMaskAsUint(ExitPayload memory payload) internal pure returns(uint256) { return payload.data[8].toUint(); } function getReceiptLogIndex(ExitPayload memory payload) internal pure returns(uint256) { return payload.data[9].toUint(); } // Receipt methods function toBytes(Receipt memory receipt) internal pure returns(bytes memory) { return receipt.raw; } function getLog(Receipt memory receipt) internal pure returns(Log memory) { RLPReader.RLPItem memory logData = receipt.data[3].toList()[receipt.logIndex]; return Log(logData, logData.toList()); } // Log methods function getEmitter(Log memory log) internal pure returns(address) { return RLPReader.toAddress(log.list[0]); } function getTopics(Log memory log) internal pure returns(LogTopics memory) { return LogTopics(log.list[1].toList()); } function getData(Log memory log) internal pure returns(bytes memory) { return log.list[2].toBytes(); } function toRlpBytes(Log memory log) internal pure returns(bytes memory) { return log.data.toRlpBytes(); } // LogTopics methods function getField(LogTopics memory topics, uint256 index) internal pure returns(RLPReader.RLPItem memory) { return topics.data[index]; } }
/* * @title MerklePatriciaVerifier * @author Sam Mayo ([email protected]) * * @dev Library for verifing merkle patricia proofs. */ pragma solidity 0.6.6; import {RLPReader} from "./RLPReader.sol"; library MerklePatriciaProof { /* * @dev Verifies a merkle patricia proof. * @param value The terminating value in the trie. * @param encodedPath The path in the trie leading to value. * @param rlpParentNodes The rlp encoded stack of nodes. * @param root The root hash of the trie. * @return The boolean validity of the proof. */ function verify( bytes memory value, bytes memory encodedPath, bytes memory rlpParentNodes, bytes32 root ) internal pure returns (bool) { RLPReader.RLPItem memory item = RLPReader.toRlpItem(rlpParentNodes); RLPReader.RLPItem[] memory parentNodes = RLPReader.toList(item); bytes memory currentNode; RLPReader.RLPItem[] memory currentNodeList; bytes32 nodeKey = root; uint256 pathPtr = 0; bytes memory path = _getNibbleArray(encodedPath); if (path.length == 0) { return false; } for (uint256 i = 0; i < parentNodes.length; i++) { if (pathPtr > path.length) { return false; } currentNode = RLPReader.toRlpBytes(parentNodes[i]); if (nodeKey != keccak256(currentNode)) { return false; } currentNodeList = RLPReader.toList(parentNodes[i]); if (currentNodeList.length == 17) { if (pathPtr == path.length) { if ( keccak256(RLPReader.toBytes(currentNodeList[16])) == keccak256(value) ) { return true; } else { return false; } } uint8 nextPathNibble = uint8(path[pathPtr]); if (nextPathNibble > 16) { return false; } nodeKey = bytes32( RLPReader.toUintStrict(currentNodeList[nextPathNibble]) ); pathPtr += 1; } else if (currentNodeList.length == 2) { uint256 traversed = _nibblesToTraverse( RLPReader.toBytes(currentNodeList[0]), path, pathPtr ); if (pathPtr + traversed == path.length) { //leaf node if ( keccak256(RLPReader.toBytes(currentNodeList[1])) == keccak256(value) ) { return true; } else { return false; } } //extension node if (traversed == 0) { return false; } pathPtr += traversed; nodeKey = bytes32(RLPReader.toUintStrict(currentNodeList[1])); } else { return false; } } } function _nibblesToTraverse( bytes memory encodedPartialPath, bytes memory path, uint256 pathPtr ) private pure returns (uint256) { uint256 len = 0; // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath // and slicedPath have elements that are each one hex character (1 nibble) bytes memory partialPath = _getNibbleArray(encodedPartialPath); bytes memory slicedPath = new bytes(partialPath.length); // pathPtr counts nibbles in path // partialPath.length is a number of nibbles for (uint256 i = pathPtr; i < pathPtr + partialPath.length; i++) { bytes1 pathNibble = path[i]; slicedPath[i - pathPtr] = pathNibble; } if (keccak256(partialPath) == keccak256(slicedPath)) { len = partialPath.length; } else { len = 0; } return len; } // bytes b must be hp encoded function _getNibbleArray(bytes memory b) internal pure returns (bytes memory) { bytes memory nibbles = ""; if (b.length > 0) { uint8 offset; uint8 hpNibble = uint8(_getNthNibbleOfBytes(0, b)); if (hpNibble == 1 || hpNibble == 3) { nibbles = new bytes(b.length * 2 - 1); bytes1 oddNibble = _getNthNibbleOfBytes(1, b); nibbles[0] = oddNibble; offset = 1; } else { nibbles = new bytes(b.length * 2 - 2); offset = 0; } for (uint256 i = offset; i < nibbles.length; i++) { nibbles[i] = _getNthNibbleOfBytes(i - offset + 2, b); } } return nibbles; } function _getNthNibbleOfBytes(uint256 n, bytes memory str) private pure returns (bytes1) { return bytes1( n % 2 == 0 ? uint8(str[n / 2]) / 0x10 : uint8(str[n / 2]) % 0x10 ); } }
pragma solidity 0.6.6; library Merkle { function checkMembership( bytes32 leaf, uint256 index, bytes32 rootHash, bytes memory proof ) internal pure returns (bool) { require(proof.length % 32 == 0, "Invalid proof length"); uint256 proofHeight = proof.length / 32; // Proof of size n means, height of the tree is n+1. // In a tree of height n+1, max #leafs possible is 2 ^ n require(index < 2 ** proofHeight, "Leaf index is too big"); bytes32 proofElement; bytes32 computedHash = leaf; for (uint256 i = 32; i <= proof.length; i += 32) { assembly { proofElement := mload(add(proof, i)) } if (index % 2 == 0) { computedHash = keccak256( abi.encodePacked(computedHash, proofElement) ); } else { computedHash = keccak256( abi.encodePacked(proofElement, computedHash) ); } index = index / 2; } return computedHash == rootHash; } }
pragma solidity 0.6.6; import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; import {EIP712Base} from "./EIP712Base.sol"; contract NativeMetaTransaction is EIP712Base { using SafeMath for uint256; bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256( bytes( "MetaTransaction(uint256 nonce,address from,bytes functionSignature)" ) ); event MetaTransactionExecuted( address userAddress, address payable relayerAddress, bytes functionSignature ); mapping(address => uint256) nonces; /* * Meta transaction structure. * No point of including value field here as if user is doing value transfer then he has the funds to pay for gas * He should call the desired function directly in that case. */ struct MetaTransaction { uint256 nonce; address from; bytes functionSignature; } function executeMetaTransaction( address userAddress, bytes memory functionSignature, bytes32 sigR, bytes32 sigS, uint8 sigV ) public payable returns (bytes memory) { MetaTransaction memory metaTx = MetaTransaction({ nonce: nonces[userAddress], from: userAddress, functionSignature: functionSignature }); require( verify(userAddress, metaTx, sigR, sigS, sigV), "Signer and signature do not match" ); // increase nonce for user (to avoid re-use) nonces[userAddress] = nonces[userAddress].add(1); emit MetaTransactionExecuted( userAddress, msg.sender, functionSignature ); // Append userAddress and relayer address at the end to extract it from calling context (bool success, bytes memory returnData) = address(this).call( abi.encodePacked(functionSignature, userAddress) ); require(success, "Function call not successful"); return returnData; } function hashMetaTransaction(MetaTransaction memory metaTx) internal pure returns (bytes32) { return keccak256( abi.encode( META_TRANSACTION_TYPEHASH, metaTx.nonce, metaTx.from, keccak256(metaTx.functionSignature) ) ); } function getNonce(address user) public view returns (uint256 nonce) { nonce = nonces[user]; } function verify( address signer, MetaTransaction memory metaTx, bytes32 sigR, bytes32 sigS, uint8 sigV ) internal view returns (bool) { require(signer != address(0), "NativeMetaTransaction: INVALID_SIGNER"); return signer == ecrecover( toTypedMessageHash(hashMetaTransaction(metaTx)), sigV, sigR, sigS ); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
pragma solidity 0.6.6; abstract contract ContextMixin { function msgSender() internal view returns (address payable sender) { if (msg.sender == address(this)) { bytes memory array = msg.data; uint256 index = msg.data.length; assembly { // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those. sender := and( mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff ) } } else { sender = msg.sender; } return sender; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
pragma solidity 0.6.6; interface IStateSender { function syncState(address receiver, bytes calldata data) external; }
pragma solidity 0.6.6; import {Initializable} from "./Initializable.sol"; contract EIP712Base is Initializable { struct EIP712Domain { string name; string version; address verifyingContract; bytes32 salt; } string constant public ERC712_VERSION = "1"; bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256( bytes( "EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)" ) ); bytes32 internal domainSeperator; // supposed to be called once while initializing. // one of the contractsa that inherits this contract follows proxy pattern // so it is not possible to do this in a constructor function _initializeEIP712( string memory name ) internal initializer { _setDomainSeperator(name); } function _setDomainSeperator(string memory name) internal { domainSeperator = keccak256( abi.encode( EIP712_DOMAIN_TYPEHASH, keccak256(bytes(name)), keccak256(bytes(ERC712_VERSION)), address(this), bytes32(getChainId()) ) ); } function getDomainSeperator() public view returns (bytes32) { return domainSeperator; } function getChainId() public pure returns (uint256) { uint256 id; assembly { id := chainid() } return id; } /** * Accept message hash and returns hash message in EIP712 compatible form * So that it can be used to recover signer from signature signed using EIP712 formatted data * https://eips.ethereum.org/EIPS/eip-712 * "\\x19" makes the encoding deterministic * "\\x01" is the version byte to make it compatible to EIP-191 */ function toTypedMessageHash(bytes32 messageHash) internal view returns (bytes32) { return keccak256( abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash) ); } }
pragma solidity 0.6.6; contract Initializable { bool inited = false; modifier initializer() { require(!inited, "already inited"); _; inited = true; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-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" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":true,"internalType":"address","name":"depositReceiver","type":"address"},{"indexed":true,"internalType":"address","name":"rootToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LockedERC20","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"userAddress","type":"address"},{"indexed":false,"internalType":"address payable","name":"relayerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_previousMapper","type":"address"},{"indexed":true,"internalType":"address","name":"_newMapper","type":"address"}],"name":"SetMapper","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"_newOwner","type":"address"}],"name":"SetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rootToken","type":"address"},{"indexed":true,"internalType":"address","name":"childToken","type":"address"},{"indexed":true,"internalType":"bytes32","name":"tokenType","type":"bytes32"}],"name":"TokenMapped","type":"event"},{"inputs":[],"name":"DEPOSIT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ERC712_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAPPER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAP_TOKEN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRANSFER_EVENT_SIG","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkpointManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_childToken","type":"address"}],"name":"childToRootToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rootToken","type":"address"}],"name":"childTokenAddress","outputs":[{"internalType":"address","name":"childToken_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"rootToken","type":"address"},{"internalType":"bytes","name":"depositData","type":"bytes"}],"name":"depositFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bytes","name":"functionSignature","type":"bytes"},{"internalType":"bytes32","name":"sigR","type":"bytes32"},{"internalType":"bytes32","name":"sigS","type":"bytes32"},{"internalType":"uint8","name":"sigV","type":"uint8"}],"name":"executeMetaTransaction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"inputData","type":"bytes"}],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_aTokenAddress","type":"address"},{"internalType":"uint256","name":"_maTokenValue","type":"uint256"}],"name":"getATokenValue","outputs":[{"internalType":"uint256","name":"aTokenValue_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getDomainSeperator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_aTokenAddress","type":"address"},{"internalType":"uint256","name":"_aTokenValue","type":"uint256"}],"name":"getMATokenValue","outputs":[{"internalType":"uint256","name":"maTokenValue_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"headerBlocks","outputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"address","name":"proposer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_stateSender","type":"address"},{"internalType":"address","name":"_checkpointManager","type":"address"},{"internalType":"address","name":"_childChainManagerAddress","type":"address"},{"internalType":"bytes32","name":"_childTokenBytecodeHash","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"rootToken","type":"address"}],"name":"mapToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mapper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_exitHash","type":"bytes32"}],"name":"processedExits","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rootToken","type":"address"}],"name":"remapToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rootToken","type":"address"}],"name":"rootToChildToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newCheckpointManager","type":"address"}],"name":"setCheckpointManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newChildChainManager","type":"address"}],"name":"setChildChainManagerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newChildChainManager","type":"address"},{"internalType":"bytes32","name":"newChildTokenBytecodeHash","type":"bytes32"}],"name":"setChildChainManagerAddressAndChildTokenBytecodeHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"newChildTokenBytecodeHash","type":"bytes32"}],"name":"setChildTokenBytecodeHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newMapper","type":"address"}],"name":"setMapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newStateSender","type":"address"}],"name":"setStateSender","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stateSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stateSenderAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040526001805460ff1916905534801561001a57600080fd5b506144ff8061002a6000396000f3fe6080604052600436106101f15760003560e01c80636cb136b01161010d578063c38a960e116100a0578063dc993a231161006f578063dc993a2314610857578063e2c49de114610803578063e3dec8fb1461088a578063ea60c7c414610954578063f4a120f7146109875761022d565b8063c38a960e146107d0578063cb10f94c14610803578063d45d760e14610818578063d81c8e52146108425761022d565b80638da5cb5b116100dc5780638da5cb5b1461073a5780639b2492c81461074f578063b017a30f14610788578063bc08452b1461079d5761022d565b80636cb136b0146106865780636e86b770146106b9578063886a69ba146106ec57806389d60963146107015761022d565b80632d0335ab1161018557806341539d4a1161015457806341539d4a146105c0578063568b80b51461061e578063607f2d421461063357806362f4f6a2146106715761022d565b80632d0335ab146104e85780633138b6f11461051b5780633408e470146105305780633805550f146105455761022d565b806313af4035116101c157806313af4035146104085780631d97c02b1461043b57806320379ee51461046e578063297a3e57146104955761022d565b8062561b7c146102325780630c53c51c1461026d5780630f7e5970146103a45780631116f918146103b95761022d565b3661022d5760405162461bcd60e51b81526004018080602001828103825260228152602001806142016022913960400191505060405180910390fd5b600080fd5b34801561023e57600080fd5b5061026b6004803603604081101561025557600080fd5b506001600160a01b0381351690602001356109ba565b005b61032f600480360360a081101561028357600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156102ad57600080fd5b8201836020820111156102bf57600080fd5b803590602001918460018302840111600160201b831117156102e057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550508235935050506020810135906040013560ff16610a83565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610369578181015183820152602001610351565b50505050905090810190601f1680156103965780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103b057600080fd5b5061032f610d86565b3480156103c557600080fd5b506103ec600480360360208110156103dc57600080fd5b50356001600160a01b0316610da3565b604080516001600160a01b039092168252519081900360200190f35b34801561041457600080fd5b5061026b6004803603602081101561042b57600080fd5b50356001600160a01b0316610e08565b34801561044757600080fd5b5061026b6004803603602081101561045e57600080fd5b50356001600160a01b0316610ec2565b34801561047a57600080fd5b5061048361103d565b60408051918252519081900360200190f35b3480156104a157600080fd5b5061026b600480360360a08110156104b857600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611043565b3480156104f457600080fd5b506104836004803603602081101561050b57600080fd5b50356001600160a01b0316611140565b34801561052757600080fd5b506103ec61115b565b34801561053c57600080fd5b5061048361116a565b34801561055157600080fd5b5061026b6004803603602081101561056857600080fd5b810190602081018135600160201b81111561058257600080fd5b82018360208201111561059457600080fd5b803590602001918460018302840111600160201b831117156105b557600080fd5b50909250905061116e565b3480156105cc57600080fd5b506105ea600480360360208110156105e357600080fd5b503561145b565b6040805195865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190f35b34801561062a57600080fd5b50610483611493565b34801561063f57600080fd5b5061065d6004803603602081101561065657600080fd5b50356114b6565b604080519115158252519081900360200190f35b34801561067d57600080fd5b506103ec6114ce565b34801561069257600080fd5b5061026b600480360360208110156106a957600080fd5b50356001600160a01b03166114dd565b3480156106c557600080fd5b506103ec600480360360208110156106dc57600080fd5b50356001600160a01b03166115a8565b3480156106f857600080fd5b506104836115c6565b34801561070d57600080fd5b506104836004803603604081101561072457600080fd5b506001600160a01b0381351690602001356115e7565b34801561074657600080fd5b506103ec611753565b34801561075b57600080fd5b506104836004803603604081101561077257600080fd5b506001600160a01b038135169060200135611762565b34801561079457600080fd5b506104836118c5565b3480156107a957600080fd5b5061026b600480360360208110156107c057600080fd5b50356001600160a01b03166118e9565b3480156107dc57600080fd5b5061026b600480360360208110156107f357600080fd5b50356001600160a01b03166119ae565b34801561080f57600080fd5b506103ec611a68565b34801561082457600080fd5b5061026b6004803603602081101561083b57600080fd5b5035611a7c565b34801561084e57600080fd5b50610483611adf565b34801561086357600080fd5b5061026b6004803603602081101561087a57600080fd5b50356001600160a01b0316611afe565b34801561089657600080fd5b5061026b600480360360608110156108ad57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156108e057600080fd5b8201836020820111156108f257600080fd5b803590602001918460018302840111600160201b8311171561091357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611bc3945050505050565b34801561096057600080fd5b506103ec6004803603602081101561097757600080fd5b50356001600160a01b0316611fd2565b34801561099357600080fd5b5061026b600480360360208110156109aa57600080fd5b50356001600160a01b0316611ff0565b600b546001600160a01b03166109ce6120da565b6001600160a01b031614610a18576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b038216610a5d5760405162461bcd60e51b815260040180806020018281038252603381526020018061441c6033913960400191505060405180910390fd5b600980546001600160a01b0319166001600160a01b039390931692909217909155600a55565b6060610a8d6140ce565b50604080516060810182526001600160a01b03881660008181526003602090815290849020548352820152908101869052610acb8782878787612138565b610b065760405162461bcd60e51b81526004018080602001828103825260218152602001806143d56021913960400191505060405180910390fd5b6001600160a01b038716600090815260036020526040902054610b3090600163ffffffff61221516565b6001600160a01b03881660008181526003602090815260408083209490945583519283523383820181905260609484018581528b51958501959095528a517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b958d9592948d94919260808501928601918190849084905b83811015610bbf578181015183820152602001610ba7565b50505050905090810190601f168015610bec5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a160006060306001600160a01b0316888a6040516020018083805190602001908083835b60208310610c3d5780518252601f199092019160209182019101610c1e565b6001836020036101000a038019825116818451168082178552505050505050905001826001600160a01b03166001600160a01b031660601b8152601401925050506040516020818303038152906040526040518082805190602001908083835b60208310610cbc5780518252601f199092019160209182019101610c9d565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610d1e576040519150601f19603f3d011682016040523d82523d6000602084013e610d23565b606091505b509150915081610d7a576040805162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c00000000604482015290519081900360640190fd5b98975050505050505050565b604051806040016040528060018152602001603160f81b81525081565b600954600a54604080516001600160f81b03196020808301919091526bffffffffffffffffffffffff19606095861b811660218401529590941b9094166035850152605580850192909252805180850390920182526075909301909252815191012090565b600b546001600160a01b0316610e1c6120da565b6001600160a01b031614610e66576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b600b546040516001600160a01b038084169216907fcbf985117192c8f614a58aaf97226bb80a754772f5f6edf06f87c675f2e6c66390600090a3600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b0316610ed66120da565b6001600160a01b031614610f20576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6000610f2b82610da3565b6001600160a01b03808416600090815260046020526040902054919250908116908216811415610f8c5760405162461bcd60e51b815260040180806020018281038252602f815260200180614167602f913960400191505060405180910390fd5b6001600160a01b03808316600090815260056020908152604080832054841680845260049092529091205490911615610fe6576001600160a01b038116600090815260046020526040902080546001600160a01b03191690555b6001600160a01b03828116600090815260056020526040902054161561102d576001600160a01b038216600090815260056020526040902080546001600160a01b03191690555b6110378484612278565b50505050565b60025490565b60075460ff161561108c576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6007805460ff1916600117905560408051808201909152601681527520aa37b5b2b72937b7ba21b430b4b726b0b730b3b2b960511b60208201526110cf9061291e565b600b80546001600160a01b03199081166001600160a01b03978816908117909255600c8054821690921790915560078054610100600160a81b031916610100968816969096029590951790945560088054851693861693909317909255600980549093169316929092179055600a55565b6001600160a01b031660009081526003602052604090205490565b6008546001600160a01b031690565b4690565b6111766140f8565b6111b583838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061297f92505050565b905060606111c2826129af565b905060006111cf836129d2565b6111d8836129f5565b6111e185612b68565b6040516020018084815260200183805190602001908083835b602083106112195780518252601f1990920191602091820191016111fa565b51815160209384036101000a6000190180199092169116179052920193845250604080518085038152938201815283519382019390932060008181526006909252929020549194505060ff161591506112a590505760405162461bcd60e51b815260040180806020018281038252602e815260200180614355602e913960400191505060405180910390fd5b6000818152600660205260409020805460ff191660011790556112c661410b565b6112cf84612b7e565b90506112d961412c565b6112e282612c68565b905060006005816112f284612cd5565b6001600160a01b0390811682526020820192909252604001600020541690508061134d5760405162461bcd60e51b81526004018080602001828103825260288152602001806141d96028913960400191505060405180910390fd5b61135686612cf8565b63ffffffff1916156113995760405162461bcd60e51b815260040180806020018281038252602b81526020018061432a602b913960400191505060405180910390fd5b6113bd6113a584612d0e565b866113af89612d15565b6113b88a612d2b565b612d41565b6113f85760405162461bcd60e51b81526004018080602001828103825260258152602001806142e06025913960400191505060405180910390fd5b611436611404876129d2565b61140d88612f88565b61141689612f9e565b61141f8a612d2b565b6114288b612fb4565b6114318c612fca565b612fe0565b506114516114426120da565b8261144c85613113565b613122565b5050505050505050565b60006020819052908152604090208054600182015460028301546003840154600490940154929391929091906001600160a01b031685565b604080516a4d41505045525f524f4c4560a81b8152905190819003600b01902081565b60008181526006602052604090205460ff165b919050565b600c546001600160a01b031690565b600b546001600160a01b03166114f16120da565b6001600160a01b03161461153b576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b0381166115805760405162461bcd60e51b81526004018080602001828103825260268152602001806143f66026913960400191505060405180910390fd5b600780546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b039081166000908152600560205260409020541690565b604080516826a0a82faa27a5a2a760b91b8152905190819003600901902081565b600080836001600160a01b0316637535d2466040518163ffffffff1660e01b815260040160206040518083038186803b15801561162357600080fd5b505afa158015611637573d6000803e3d6000fd5b505050506040513d602081101561164d57600080fd5b5051604080516358b50cef60e11b815290519192506000916001600160a01b038085169263d15e0053929189169163b16a19de91600480820192602092909190829003018186803b1580156116a157600080fd5b505afa1580156116b5573d6000803e3d6000fd5b505050506040513d60208110156116cb57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152516024808301926020929190829003018186803b15801561171257600080fd5b505afa158015611726573d6000803e3d6000fd5b505050506040513d602081101561173c57600080fd5b5051905061174a8482613266565b95945050505050565b600b546001600160a01b031690565b600080836001600160a01b0316637535d2466040518163ffffffff1660e01b815260040160206040518083038186803b15801561179e57600080fd5b505afa1580156117b2573d6000803e3d6000fd5b505050506040513d60208110156117c857600080fd5b5051604080516358b50cef60e11b815290519192506000916001600160a01b038085169263d15e0053929189169163b16a19de91600480820192602092909190829003018186803b15801561181c57600080fd5b505afa158015611830573d6000803e3d6000fd5b505050506040513d602081101561184657600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152516024808301926020929190829003018186803b15801561188d57600080fd5b505afa1580156118a1573d6000803e3d6000fd5b505050506040513d60208110156118b757600080fd5b5051905061174a848261336e565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef81565b600b546001600160a01b03166118fd6120da565b6001600160a01b031614611947576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b03811661198c5760405162461bcd60e51b815260040180806020018281038252602c815260200180614383602c913960400191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b03166119c26120da565b6001600160a01b031614611a0c576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b600c546040516001600160a01b038084169216907fc3ccb9ca599457fe5a9bb338f84c2f853b1898c3a6e7eba842d95b0f017a7fa190600090a3600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60075461010090046001600160a01b031690565b600b546001600160a01b0316611a906120da565b6001600160a01b031614611ada576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b600a55565b604080516611115413d4d25560ca1b8152905190819003600701902081565b600b546001600160a01b0316611b126120da565b6001600160a01b031614611b5c576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b038116611ba15760405162461bcd60e51b815260040180806020018281038252603381526020018061441c6033913960400191505060405180910390fd5b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382811660009081526004602052604090205416611c195760405162461bcd60e51b81526004018080602001828103825260288152602001806141d96028913960400191505060405180910390fd5b6001600160a01b038316611c5e5760405162461bcd60e51b81526004018080602001828103825260248152602001806142236024913960400191505060405180910390fd5b6000818060200190516020811015611c7557600080fd5b505190506000611c836120da565b9050836001600160a01b0316856001600160a01b0316826001600160a01b03167f9b217a401a5ddf7c4d474074aff9958a18d48690d77cc2151c4706aa7348b401856040518082815260200191505060405180910390a4611cf56001600160a01b03851682308563ffffffff61344416565b6000611d0185846115e7565b905060008451905060208501945060208103855281856040516020018083815260200182805190602001908083835b60208310611d4f5780518252601f199092019160209182019101611d30565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529450606087878760405160200180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611dfb578181015183820152602001611de3565b50505050905090810190601f168015611e285780820380516001836020036101000a031916815260200191505b5060408051808303601f19018152828252600780546009546611115413d4d25560ca1b865284519586900390920185206020808701828152878701968752855160608901528551959d506101009093046001600160a01b039081169c506316f198319b50909316985096508a955093608001919085019080838360005b83811015611ebd578181015183820152602001611ea5565b50505050905090810190601f168015611eea5780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040526040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611f63578181015183820152602001611f4b565b50505050905090810190601f168015611f905780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611fb057600080fd5b505af1158015611fc4573d6000803e3d6000fd5b505050505050505050505050565b6001600160a01b039081166000908152600460205260409020541690565b6000611ffa6120da565b600c549091506001600160a01b03808316911614806120265750600b546001600160a01b038281169116145b612067576040805162461bcd60e51b815260206004820152600d60248201526c24b9903737ba1036b0b83832b960991b604482015290519081900360640190fd5b6001600160a01b0382811660009081526004602052604090205416156120be5760405162461bcd60e51b81526004018080602001828103825260268152602001806142966026913960400191505060405180910390fd5b60006120c983610da3565b90506120d58382612278565b505050565b6000333014156121325760606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506121359050565b50335b90565b60006001600160a01b03861661217f5760405162461bcd60e51b81526004018080602001828103825260258152602001806143056025913960400191505060405180910390fd5b600161219261218d8761349e565b61352a565b83868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156121ec573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b60008282018381101561226f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6001600160a01b03808316600081815260046020908152604080832080549587166001600160a01b031996871681179091558084526005909252808320805490951684179094559251909291907f9e651a8866fbea043e911d816ec254b0e3c992c06fff32d605e72362d6023bd9908490a4606082836001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561232657600080fd5b505afa15801561233a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561236357600080fd5b8101908080516040519392919084600160201b82111561238257600080fd5b90830190602082018581111561239757600080fd5b8251600160201b8111828201881017156123b057600080fd5b82525081516020918201929091019080838360005b838110156123dd5781810151838201526020016123c5565b50505050905090810190601f16801561240a5780820380516001836020036101000a031916815260200191505b50604052505050604051602001808065026b0ba34b1960d51b81525060060182805190602001908083835b602083106124545780518252601f199092019160209182019101612435565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052846001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156124c157600080fd5b505afa1580156124d5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156124fe57600080fd5b8101908080516040519392919084600160201b82111561251d57600080fd5b90830190602082018581111561253257600080fd5b8251600160201b81118282018810171561254b57600080fd5b82525081516020918201929091019080838360005b83811015612578578181015183820152602001612560565b50505050905090810190601f1680156125a55780820380516001836020036101000a031916815260200191505b506040525050506040516020018080606d60f81b81525060010182805190602001908083835b602083106125ea5780518252601f1990920191602091820191016125cb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561265757600080fd5b505afa15801561266b573d6000803e3d6000fd5b505050506040513d602081101561268157600080fd5b5051604080516001600160a01b038616602082810191825260ff8516608080850191909152938301938452865160a08401528651919392606081019260c09091019188019080838360005b838110156126e45781810151838201526020016126cc565b50505050905090810190601f1680156127115780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838360005b8381101561274457818101518382015260200161272c565b50505050905090810190601f1680156127715780820380516001836020036101000a031916815260200191505b5060408051601f19818403018152828252600754600980546826a0a82faa27a5a2a760b91b865284519586900390910185206020868101828152878701968752855160608901528551959f506001600160a01b0361010090950485169e506316f198319d50929093169a5098508c975095509193506080909201919085019080838360005b8381101561280e5781810151838201526020016127f6565b50505050905090810190601f16801561283b5780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040526040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156128b457818101518382015260200161289c565b50505050905090810190601f1680156128e15780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561290157600080fd5b505af1158015612915573d6000803e3d6000fd5b50505050505050565b60015460ff1615612967576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b61297081613576565b506001805460ff191681179055565b6129876140f8565b606061299a61299584613632565b613657565b60408051602081019091529081529392505050565b606061227282600001516008815181106129c557fe5b602002602001015161373f565b600061227282600001516002815181106129e857fe5b60200260200101516137bc565b6040805160208101909152600081528151606091901561227257600080612a1d600086613809565b60f81c90506001811480612a3457508060ff166003145b15612ac357600185516002020367ffffffffffffffff81118015612a5757600080fd5b506040519080825280601f01601f191660200182016040528015612a82576020820181803683370190505b5092506000612a92600187613809565b90508084600081518110612aa257fe5b60200101906001600160f81b031916908160001a9053506001925050612b14565b600285516002020367ffffffffffffffff81118015612ae157600080fd5b506040519080825280601f01601f191660200182016040528015612b0c576020820181803683370190505b509250600091505b60ff82165b8351811015612b5f57612b348360ff16820360020187613809565b848281518110612b4057fe5b60200101906001600160f81b031916908160001a905350600101612b19565b50505092915050565b600061227282600001516009815181106129e857fe5b612b8661410b565b612b9a82600001516006815181106129c557fe5b6020820152612ba761414c565b612bb48260200151613632565b9050612bbf81613866565b15612bd457612bcd81613657565b8252612c54565b602082015180516060906000190167ffffffffffffffff81118015612bf857600080fd5b506040519080825280601f01601f191660200182016040528015612c23576020820181803683370190505b509050600080836021019150826020019050612c41828285516138a0565b612c4d61299584613632565b8652505050505b612c5d83612b68565b604083015250919050565b612c7061412c565b612c7861414c565b612c998360000151600381518110612c8c57fe5b6020026020010151613657565b836040015181518110612ca857fe5b602002602001015190506040518060400160405280828152602001612ccc83613657565b90529392505050565b60006122728260200151600081518110612ceb57fe5b60200260200101516138eb565b600061227282600001516008815181106129e857fe5b6020015190565b606061227282600001516007815181106129c557fe5b600061227282600001516005815181106129e857fe5b6000612d4b61414c565b612d5484613632565b90506060612d6182613657565b905060608085600082612d738b6129f5565b9050805160001415612d8f576000975050505050505050612f80565b60005b8651811015612f77578151831115612db557600098505050505050505050612f80565b612dd1878281518110612dc457fe5b6020026020010151613905565b955085805190602001208414612df257600098505050505050505050612f80565b612e01878281518110612c8c57fe5b9450845160111415612ebe578151831415612e5d578c80519060200120612e2e866010815181106129c557fe5b805190602001201415612e4c57600198505050505050505050612f80565b600098505050505050505050612f80565b6000828481518110612e6b57fe5b016020015160f81c90506010811115612e905760009950505050505050505050612f80565b612eaf868260ff1681518110612ea257fe5b6020026020010151613984565b94505060019290920191612f6f565b845160021415612e4c576000612ee4612edd876000815181106129c557fe5b84866139a1565b905082518185011415612f3a578d80519060200120612f09876001815181106129c557fe5b805190602001201415612f285760019950505050505050505050612f80565b60009950505050505050505050612f80565b80612f515760009950505050505050505050612f80565b8084019350612f6686600181518110612ea257fe5b9450612f6f9050565b600101612d92565b50505050505050505b949350505050565b600061227282600001516003815181106129e857fe5b600061227282600001516004815181106129e857fe5b600061227282600001516000815181106129e857fe5b606061227282600001516001815181106129c557fe5b600854604080516320a9cea560e11b81526004810185905290516000928392839283926001600160a01b0316916341539d4a9160248083019260a0929190829003018186803b15801561303257600080fd5b505afa158015613046573d6000803e3d6000fd5b505050506040513d60a081101561305c57600080fd5b508051602082015160609092015190945090925090506130cb6130858b8463ffffffff613a8216565b6040805160208082018f90528183018e9052606082018d905260808083018d90528351808403909101815260a0909201909252805191012090858863ffffffff613adf16565b6131065760405162461bcd60e51b81526004018080602001828103825260268152602001806143af6026913960400191505060405180910390fd5b9998505050505050505050565b60606122728260000151613905565b606061313061299583613632565b9050606061314482600181518110612c8c57fe5b90507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60001b61317a826000815181106129e857fe5b146131b65760405162461bcd60e51b815260040180806020018281038252602981526020018061444f6029913960400191505060405180910390fd5b60006131c8826001815181106129e857fe5b905060006001600160a01b03166131e5836002815181106129e857fe5b6001600160a01b03161461322a5760405162461bcd60e51b81526004018080602001828103825260288152602001806144a26028913960400191505060405180910390fd5b600061323c846002815181106129e857fe5b9050600061324a8783611762565b90506114516001600160a01b038816848363ffffffff613c3516565b6000816132ae576040805162461bcd60e51b81526020600482015260116024820152700703237206469766973696f6e206279203607c1b604482015290519081900360640190fd5b6b033b2e3c9fd0803ce80000008381029081048414613314576040805162461bcd60e51b815260206004820152601b60248201527f703237206d756c7469706c69636174696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60028304908101908082101561335b5760405162461bcd60e51b81526004018080602001828103825260248152602001806142bc6024913960400191505060405180910390fd5b83828161336457fe5b0495945050505050565b600082820280613382576000915050612272565b83818161338b57fe5b0483146133df576040805162461bcd60e51b815260206004820152601b60248201527f703237206d756c7469706c69636174696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6b019d971e4fe8401e740000009081019081101561342e5760405162461bcd60e51b81526004018080602001828103825260248152602001806142bc6024913960400191505060405180910390fd5b6b033b2e3c9fd0803ce800000090049392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611037908590613c83565b600060405180608001604052806043815260200161419660439139805190602001208260000151836020015184604001518051906020012060405160200180858152602001848152602001836001600160a01b03166001600160a01b03168152602001828152602001945050505050604051602081830303815290604052805190602001209050919050565b600061353461103d565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b6040518060800160405280604f8152602001614247604f913980516020918201208251838301206040805180820190915260018152603160f81b930192909252907fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6306135e161116a565b604080516020808201979097528082019590955260608501939093526001600160a01b03909116608084015260a0808401919091528151808403909101815260c09092019052805191012060025550565b61363a61414c565b506040805180820190915281518152602082810190820152919050565b606061366282613866565b61366b57600080fd5b600061367683613d34565b905060608167ffffffffffffffff8111801561369157600080fd5b506040519080825280602002602001820160405280156136cb57816020015b6136b861414c565b8152602001906001900390816136b05790505b50905060006136dd8560200151613d90565b60208601510190506000805b84811015613734576136fa83613df3565b915060405180604001604052808381526020018481525084828151811061371d57fe5b6020908102919091010152918101916001016136e9565b509195945050505050565b805160609061374d57600080fd5b60008061375984613e87565b9150915060608167ffffffffffffffff8111801561377657600080fd5b506040519080825280601f01601f1916602001820160405280156137a1576020820181803683370190505b509050602081016137b3848285613ead565b50949350505050565b8051600090158015906137d157508151602110155b6137da57600080fd5b6000806137e684613e87565b815191935091506020821015612f805760208290036101000a9004949350505050565b6000600283061561383a57601082600285048151811061382557fe5b016020015160f81c8161383457fe5b0661385c565b601082600285048151811061384b57fe5b016020015160f81c8161385a57fe5b045b60f81b9392505050565b8051600090613877575060006114c9565b6020820151805160001a9060c0821015613896576000925050506114c9565b5060019392505050565b806138aa576120d5565b5b602081106138ca578251825260209283019290910190601f19016138ab565b915181516020939093036101000a6000190180199091169216919091179052565b80516000906015146138fc57600080fd5b612272826137bc565b606080826000015167ffffffffffffffff8111801561392357600080fd5b506040519080825280601f01601f19166020018201604052801561394e576020820181803683370190505b5090508051600014156139625790506114c9565b600081602001905061397d8460200151828660000151613ead565b5092915050565b805160009060211461399557600080fd5b50602001516001015190565b60008060606139af866129f5565b90506060815167ffffffffffffffff811180156139cb57600080fd5b506040519080825280601f01601f1916602001820160405280156139f6576020820181803683370190505b509050845b82518601811015613a50576000878281518110613a1457fe5b602001015160f81c60f81b9050808388840381518110613a3057fe5b60200101906001600160f81b031916908160001a905350506001016139fb565b50808051906020012082805190602001201415613a705781519250613a75565b600092505b50909150505b9392505050565b600082821115613ad9576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006020825181613aec57fe5b0615613b36576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e0e4dedecc40d8cadccee8d60631b604482015290519081900360640190fd5b60006020835181613b4357fe5b0490508060020a8510613b95576040805162461bcd60e51b81526020600482015260156024820152744c65616620696e64657820697320746f6f2062696760581b604482015290519081900360640190fd5b60008660205b85518111613c275785810151925060028806613be75781836040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209150613c19565b828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600288049750602001613b9b565b509094149695505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526120d59084905b6060613cd8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613efe9092919063ffffffff16565b8051909150156120d557808060200190516020811015613cf757600080fd5b50516120d55760405162461bcd60e51b815260040180806020018281038252602a815260200180614478602a913960400191505060405180910390fd5b8051600090613d45575060006114c9565b60008090506000613d598460200151613d90565b602085015185519181019250015b80821015613d8757613d7882613df3565b60019093019290910190613d67565b50909392505050565b8051600090811a6080811015613daa5760009150506114c9565b60b8811080613dc5575060c08110801590613dc5575060f881105b15613dd45760019150506114c9565b60c0811015613de85760b5190190506114c9565b60f5190190506114c9565b80516000908190811a6080811015613e0e576001915061397d565b60b8811015613e2357607e198101915061397d565b60c0811015613e505760b78103600185019450806020036101000a8551046001820181019350505061397d565b60f8811015613e655760be198101915061397d565b60019390930151602084900360f7016101000a900490920160f5190192915050565b6000806000613e998460200151613d90565b602085015194519481019594039392505050565b80613eb7576120d5565b5b60208110613ed7578251825260209283019290910190601f1901613eb8565b80156120d557915181516020939093036101000a6000190180199091169216919091179052565b6060612f80848460008585613f1285614024565b613f63576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310613fa25780518252601f199092019160209182019101613f83565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614004576040519150601f19603f3d011682016040523d82523d6000602084013e614009565b606091505b509150915061401982828661402a565b979650505050505050565b3b151590565b60608315614039575081613a7b565b8251156140495782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561409357818101518382015260200161407b565b50505050905090810190601f1680156140c05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60405180606001604052806000815260200160006001600160a01b03168152602001606081525090565b6040518060200160405280606081525090565b60405180606001604052806060815260200160608152602001600081525090565b604051806040016040528061413f61414c565b8152602001606081525090565b60405180604001604052806000815260200160008152509056fe41546f6b656e526f6f74436861696e4d616e616765723a204368696c6420746f6b656e206973207468652073616d654d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e61747572652941546f6b656e526f6f74436861696e4d616e616765723a20544f4b454e5f4e4f545f4d415050454443616e6e6f742073656e6420455448206f7665722061546f6b656e2062726964676541546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f55534552454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c6164647265737320766572696679696e67436f6e74726163742c627974657333322073616c742941546f6b656e526f6f74436861696e4d616e616765723a20414c52454144595f4d4150504544703237206d756c7469706c69636174696f6e206164646974696f6e206f766572666c6f7741546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f50524f4f464e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5349474e455241546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f4252414e43485f4d41534b41546f6b656e526f6f74436861696e4d616e616765723a20455849545f414c52454144595f50524f434553534544526f6f74436861696e4d616e616765723a204241445f4e45575f434845434b504f494e545f4d414e4147455241546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f4845414445525369676e657220616e64207369676e617475726520646f206e6f74206d61746368526f6f74436861696e4d616e616765723a204241445f4e45575f53544154455f53454e44455241546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f4348494c445f434841494e5f4144445245535341546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f5349474e41545552455361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656441546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f5245434549564552a264697066735822122037454f12bec2f2dc5b85f7a30be5e9fa05dca30edf2849f968433600081f42ca64736f6c63430006060033
Deployed Bytecode
0x6080604052600436106101f15760003560e01c80636cb136b01161010d578063c38a960e116100a0578063dc993a231161006f578063dc993a2314610857578063e2c49de114610803578063e3dec8fb1461088a578063ea60c7c414610954578063f4a120f7146109875761022d565b8063c38a960e146107d0578063cb10f94c14610803578063d45d760e14610818578063d81c8e52146108425761022d565b80638da5cb5b116100dc5780638da5cb5b1461073a5780639b2492c81461074f578063b017a30f14610788578063bc08452b1461079d5761022d565b80636cb136b0146106865780636e86b770146106b9578063886a69ba146106ec57806389d60963146107015761022d565b80632d0335ab1161018557806341539d4a1161015457806341539d4a146105c0578063568b80b51461061e578063607f2d421461063357806362f4f6a2146106715761022d565b80632d0335ab146104e85780633138b6f11461051b5780633408e470146105305780633805550f146105455761022d565b806313af4035116101c157806313af4035146104085780631d97c02b1461043b57806320379ee51461046e578063297a3e57146104955761022d565b8062561b7c146102325780630c53c51c1461026d5780630f7e5970146103a45780631116f918146103b95761022d565b3661022d5760405162461bcd60e51b81526004018080602001828103825260228152602001806142016022913960400191505060405180910390fd5b600080fd5b34801561023e57600080fd5b5061026b6004803603604081101561025557600080fd5b506001600160a01b0381351690602001356109ba565b005b61032f600480360360a081101561028357600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156102ad57600080fd5b8201836020820111156102bf57600080fd5b803590602001918460018302840111600160201b831117156102e057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550508235935050506020810135906040013560ff16610a83565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610369578181015183820152602001610351565b50505050905090810190601f1680156103965780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103b057600080fd5b5061032f610d86565b3480156103c557600080fd5b506103ec600480360360208110156103dc57600080fd5b50356001600160a01b0316610da3565b604080516001600160a01b039092168252519081900360200190f35b34801561041457600080fd5b5061026b6004803603602081101561042b57600080fd5b50356001600160a01b0316610e08565b34801561044757600080fd5b5061026b6004803603602081101561045e57600080fd5b50356001600160a01b0316610ec2565b34801561047a57600080fd5b5061048361103d565b60408051918252519081900360200190f35b3480156104a157600080fd5b5061026b600480360360a08110156104b857600080fd5b506001600160a01b0381358116916020810135821691604082013581169160608101359091169060800135611043565b3480156104f457600080fd5b506104836004803603602081101561050b57600080fd5b50356001600160a01b0316611140565b34801561052757600080fd5b506103ec61115b565b34801561053c57600080fd5b5061048361116a565b34801561055157600080fd5b5061026b6004803603602081101561056857600080fd5b810190602081018135600160201b81111561058257600080fd5b82018360208201111561059457600080fd5b803590602001918460018302840111600160201b831117156105b557600080fd5b50909250905061116e565b3480156105cc57600080fd5b506105ea600480360360208110156105e357600080fd5b503561145b565b6040805195865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190f35b34801561062a57600080fd5b50610483611493565b34801561063f57600080fd5b5061065d6004803603602081101561065657600080fd5b50356114b6565b604080519115158252519081900360200190f35b34801561067d57600080fd5b506103ec6114ce565b34801561069257600080fd5b5061026b600480360360208110156106a957600080fd5b50356001600160a01b03166114dd565b3480156106c557600080fd5b506103ec600480360360208110156106dc57600080fd5b50356001600160a01b03166115a8565b3480156106f857600080fd5b506104836115c6565b34801561070d57600080fd5b506104836004803603604081101561072457600080fd5b506001600160a01b0381351690602001356115e7565b34801561074657600080fd5b506103ec611753565b34801561075b57600080fd5b506104836004803603604081101561077257600080fd5b506001600160a01b038135169060200135611762565b34801561079457600080fd5b506104836118c5565b3480156107a957600080fd5b5061026b600480360360208110156107c057600080fd5b50356001600160a01b03166118e9565b3480156107dc57600080fd5b5061026b600480360360208110156107f357600080fd5b50356001600160a01b03166119ae565b34801561080f57600080fd5b506103ec611a68565b34801561082457600080fd5b5061026b6004803603602081101561083b57600080fd5b5035611a7c565b34801561084e57600080fd5b50610483611adf565b34801561086357600080fd5b5061026b6004803603602081101561087a57600080fd5b50356001600160a01b0316611afe565b34801561089657600080fd5b5061026b600480360360608110156108ad57600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156108e057600080fd5b8201836020820111156108f257600080fd5b803590602001918460018302840111600160201b8311171561091357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611bc3945050505050565b34801561096057600080fd5b506103ec6004803603602081101561097757600080fd5b50356001600160a01b0316611fd2565b34801561099357600080fd5b5061026b600480360360208110156109aa57600080fd5b50356001600160a01b0316611ff0565b600b546001600160a01b03166109ce6120da565b6001600160a01b031614610a18576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b038216610a5d5760405162461bcd60e51b815260040180806020018281038252603381526020018061441c6033913960400191505060405180910390fd5b600980546001600160a01b0319166001600160a01b039390931692909217909155600a55565b6060610a8d6140ce565b50604080516060810182526001600160a01b03881660008181526003602090815290849020548352820152908101869052610acb8782878787612138565b610b065760405162461bcd60e51b81526004018080602001828103825260218152602001806143d56021913960400191505060405180910390fd5b6001600160a01b038716600090815260036020526040902054610b3090600163ffffffff61221516565b6001600160a01b03881660008181526003602090815260408083209490945583519283523383820181905260609484018581528b51958501959095528a517f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b958d9592948d94919260808501928601918190849084905b83811015610bbf578181015183820152602001610ba7565b50505050905090810190601f168015610bec5780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a160006060306001600160a01b0316888a6040516020018083805190602001908083835b60208310610c3d5780518252601f199092019160209182019101610c1e565b6001836020036101000a038019825116818451168082178552505050505050905001826001600160a01b03166001600160a01b031660601b8152601401925050506040516020818303038152906040526040518082805190602001908083835b60208310610cbc5780518252601f199092019160209182019101610c9d565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610d1e576040519150601f19603f3d011682016040523d82523d6000602084013e610d23565b606091505b509150915081610d7a576040805162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c00000000604482015290519081900360640190fd5b98975050505050505050565b604051806040016040528060018152602001603160f81b81525081565b600954600a54604080516001600160f81b03196020808301919091526bffffffffffffffffffffffff19606095861b811660218401529590941b9094166035850152605580850192909252805180850390920182526075909301909252815191012090565b600b546001600160a01b0316610e1c6120da565b6001600160a01b031614610e66576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b600b546040516001600160a01b038084169216907fcbf985117192c8f614a58aaf97226bb80a754772f5f6edf06f87c675f2e6c66390600090a3600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b0316610ed66120da565b6001600160a01b031614610f20576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6000610f2b82610da3565b6001600160a01b03808416600090815260046020526040902054919250908116908216811415610f8c5760405162461bcd60e51b815260040180806020018281038252602f815260200180614167602f913960400191505060405180910390fd5b6001600160a01b03808316600090815260056020908152604080832054841680845260049092529091205490911615610fe6576001600160a01b038116600090815260046020526040902080546001600160a01b03191690555b6001600160a01b03828116600090815260056020526040902054161561102d576001600160a01b038216600090815260056020526040902080546001600160a01b03191690555b6110378484612278565b50505050565b60025490565b60075460ff161561108c576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b6007805460ff1916600117905560408051808201909152601681527520aa37b5b2b72937b7ba21b430b4b726b0b730b3b2b960511b60208201526110cf9061291e565b600b80546001600160a01b03199081166001600160a01b03978816908117909255600c8054821690921790915560078054610100600160a81b031916610100968816969096029590951790945560088054851693861693909317909255600980549093169316929092179055600a55565b6001600160a01b031660009081526003602052604090205490565b6008546001600160a01b031690565b4690565b6111766140f8565b6111b583838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061297f92505050565b905060606111c2826129af565b905060006111cf836129d2565b6111d8836129f5565b6111e185612b68565b6040516020018084815260200183805190602001908083835b602083106112195780518252601f1990920191602091820191016111fa565b51815160209384036101000a6000190180199092169116179052920193845250604080518085038152938201815283519382019390932060008181526006909252929020549194505060ff161591506112a590505760405162461bcd60e51b815260040180806020018281038252602e815260200180614355602e913960400191505060405180910390fd5b6000818152600660205260409020805460ff191660011790556112c661410b565b6112cf84612b7e565b90506112d961412c565b6112e282612c68565b905060006005816112f284612cd5565b6001600160a01b0390811682526020820192909252604001600020541690508061134d5760405162461bcd60e51b81526004018080602001828103825260288152602001806141d96028913960400191505060405180910390fd5b61135686612cf8565b63ffffffff1916156113995760405162461bcd60e51b815260040180806020018281038252602b81526020018061432a602b913960400191505060405180910390fd5b6113bd6113a584612d0e565b866113af89612d15565b6113b88a612d2b565b612d41565b6113f85760405162461bcd60e51b81526004018080602001828103825260258152602001806142e06025913960400191505060405180910390fd5b611436611404876129d2565b61140d88612f88565b61141689612f9e565b61141f8a612d2b565b6114288b612fb4565b6114318c612fca565b612fe0565b506114516114426120da565b8261144c85613113565b613122565b5050505050505050565b60006020819052908152604090208054600182015460028301546003840154600490940154929391929091906001600160a01b031685565b604080516a4d41505045525f524f4c4560a81b8152905190819003600b01902081565b60008181526006602052604090205460ff165b919050565b600c546001600160a01b031690565b600b546001600160a01b03166114f16120da565b6001600160a01b03161461153b576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b0381166115805760405162461bcd60e51b81526004018080602001828103825260268152602001806143f66026913960400191505060405180910390fd5b600780546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6001600160a01b039081166000908152600560205260409020541690565b604080516826a0a82faa27a5a2a760b91b8152905190819003600901902081565b600080836001600160a01b0316637535d2466040518163ffffffff1660e01b815260040160206040518083038186803b15801561162357600080fd5b505afa158015611637573d6000803e3d6000fd5b505050506040513d602081101561164d57600080fd5b5051604080516358b50cef60e11b815290519192506000916001600160a01b038085169263d15e0053929189169163b16a19de91600480820192602092909190829003018186803b1580156116a157600080fd5b505afa1580156116b5573d6000803e3d6000fd5b505050506040513d60208110156116cb57600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152516024808301926020929190829003018186803b15801561171257600080fd5b505afa158015611726573d6000803e3d6000fd5b505050506040513d602081101561173c57600080fd5b5051905061174a8482613266565b95945050505050565b600b546001600160a01b031690565b600080836001600160a01b0316637535d2466040518163ffffffff1660e01b815260040160206040518083038186803b15801561179e57600080fd5b505afa1580156117b2573d6000803e3d6000fd5b505050506040513d60208110156117c857600080fd5b5051604080516358b50cef60e11b815290519192506000916001600160a01b038085169263d15e0053929189169163b16a19de91600480820192602092909190829003018186803b15801561181c57600080fd5b505afa158015611830573d6000803e3d6000fd5b505050506040513d602081101561184657600080fd5b5051604080516001600160e01b031960e085901b1681526001600160a01b039092166004830152516024808301926020929190829003018186803b15801561188d57600080fd5b505afa1580156118a1573d6000803e3d6000fd5b505050506040513d60208110156118b757600080fd5b5051905061174a848261336e565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef81565b600b546001600160a01b03166118fd6120da565b6001600160a01b031614611947576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b03811661198c5760405162461bcd60e51b815260040180806020018281038252602c815260200180614383602c913960400191505060405180910390fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b600b546001600160a01b03166119c26120da565b6001600160a01b031614611a0c576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b600c546040516001600160a01b038084169216907fc3ccb9ca599457fe5a9bb338f84c2f853b1898c3a6e7eba842d95b0f017a7fa190600090a3600c80546001600160a01b0319166001600160a01b0392909216919091179055565b60075461010090046001600160a01b031690565b600b546001600160a01b0316611a906120da565b6001600160a01b031614611ada576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b600a55565b604080516611115413d4d25560ca1b8152905190819003600701902081565b600b546001600160a01b0316611b126120da565b6001600160a01b031614611b5c576040805162461bcd60e51b815260206004820152600c60248201526b24b9903737ba1037bbb732b960a11b604482015290519081900360640190fd5b6001600160a01b038116611ba15760405162461bcd60e51b815260040180806020018281038252603381526020018061441c6033913960400191505060405180910390fd5b600980546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382811660009081526004602052604090205416611c195760405162461bcd60e51b81526004018080602001828103825260288152602001806141d96028913960400191505060405180910390fd5b6001600160a01b038316611c5e5760405162461bcd60e51b81526004018080602001828103825260248152602001806142236024913960400191505060405180910390fd5b6000818060200190516020811015611c7557600080fd5b505190506000611c836120da565b9050836001600160a01b0316856001600160a01b0316826001600160a01b03167f9b217a401a5ddf7c4d474074aff9958a18d48690d77cc2151c4706aa7348b401856040518082815260200191505060405180910390a4611cf56001600160a01b03851682308563ffffffff61344416565b6000611d0185846115e7565b905060008451905060208501945060208103855281856040516020018083815260200182805190602001908083835b60208310611d4f5780518252601f199092019160209182019101611d30565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040529450606087878760405160200180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611dfb578181015183820152602001611de3565b50505050905090810190601f168015611e285780820380516001836020036101000a031916815260200191505b5060408051808303601f19018152828252600780546009546611115413d4d25560ca1b865284519586900390920185206020808701828152878701968752855160608901528551959d506101009093046001600160a01b039081169c506316f198319b50909316985096508a955093608001919085019080838360005b83811015611ebd578181015183820152602001611ea5565b50505050905090810190601f168015611eea5780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040526040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b83811015611f63578181015183820152602001611f4b565b50505050905090810190601f168015611f905780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015611fb057600080fd5b505af1158015611fc4573d6000803e3d6000fd5b505050505050505050505050565b6001600160a01b039081166000908152600460205260409020541690565b6000611ffa6120da565b600c549091506001600160a01b03808316911614806120265750600b546001600160a01b038281169116145b612067576040805162461bcd60e51b815260206004820152600d60248201526c24b9903737ba1036b0b83832b960991b604482015290519081900360640190fd5b6001600160a01b0382811660009081526004602052604090205416156120be5760405162461bcd60e51b81526004018080602001828103825260268152602001806142966026913960400191505060405180910390fd5b60006120c983610da3565b90506120d58382612278565b505050565b6000333014156121325760606000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506121359050565b50335b90565b60006001600160a01b03861661217f5760405162461bcd60e51b81526004018080602001828103825260258152602001806143056025913960400191505060405180910390fd5b600161219261218d8761349e565b61352a565b83868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156121ec573d6000803e3d6000fd5b505050602060405103516001600160a01b0316866001600160a01b031614905095945050505050565b60008282018381101561226f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b6001600160a01b03808316600081815260046020908152604080832080549587166001600160a01b031996871681179091558084526005909252808320805490951684179094559251909291907f9e651a8866fbea043e911d816ec254b0e3c992c06fff32d605e72362d6023bd9908490a4606082836001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b15801561232657600080fd5b505afa15801561233a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561236357600080fd5b8101908080516040519392919084600160201b82111561238257600080fd5b90830190602082018581111561239757600080fd5b8251600160201b8111828201881017156123b057600080fd5b82525081516020918201929091019080838360005b838110156123dd5781810151838201526020016123c5565b50505050905090810190601f16801561240a5780820380516001836020036101000a031916815260200191505b50604052505050604051602001808065026b0ba34b1960d51b81525060060182805190602001908083835b602083106124545780518252601f199092019160209182019101612435565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052846001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156124c157600080fd5b505afa1580156124d5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156124fe57600080fd5b8101908080516040519392919084600160201b82111561251d57600080fd5b90830190602082018581111561253257600080fd5b8251600160201b81118282018810171561254b57600080fd5b82525081516020918201929091019080838360005b83811015612578578181015183820152602001612560565b50505050905090810190601f1680156125a55780820380516001836020036101000a031916815260200191505b506040525050506040516020018080606d60f81b81525060010182805190602001908083835b602083106125ea5780518252601f1990920191602091820191016125cb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052856001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561265757600080fd5b505afa15801561266b573d6000803e3d6000fd5b505050506040513d602081101561268157600080fd5b5051604080516001600160a01b038616602082810191825260ff8516608080850191909152938301938452865160a08401528651919392606081019260c09091019188019080838360005b838110156126e45781810151838201526020016126cc565b50505050905090810190601f1680156127115780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838360005b8381101561274457818101518382015260200161272c565b50505050905090810190601f1680156127715780820380516001836020036101000a031916815260200191505b5060408051601f19818403018152828252600754600980546826a0a82faa27a5a2a760b91b865284519586900390910185206020868101828152878701968752855160608901528551959f506001600160a01b0361010090950485169e506316f198319d50929093169a5098508c975095509193506080909201919085019080838360005b8381101561280e5781810151838201526020016127f6565b50505050905090810190601f16801561283b5780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040526040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200180602001828103825283818151815260200191508051906020019080838360005b838110156128b457818101518382015260200161289c565b50505050905090810190601f1680156128e15780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561290157600080fd5b505af1158015612915573d6000803e3d6000fd5b50505050505050565b60015460ff1615612967576040805162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481a5b9a5d195960921b604482015290519081900360640190fd5b61297081613576565b506001805460ff191681179055565b6129876140f8565b606061299a61299584613632565b613657565b60408051602081019091529081529392505050565b606061227282600001516008815181106129c557fe5b602002602001015161373f565b600061227282600001516002815181106129e857fe5b60200260200101516137bc565b6040805160208101909152600081528151606091901561227257600080612a1d600086613809565b60f81c90506001811480612a3457508060ff166003145b15612ac357600185516002020367ffffffffffffffff81118015612a5757600080fd5b506040519080825280601f01601f191660200182016040528015612a82576020820181803683370190505b5092506000612a92600187613809565b90508084600081518110612aa257fe5b60200101906001600160f81b031916908160001a9053506001925050612b14565b600285516002020367ffffffffffffffff81118015612ae157600080fd5b506040519080825280601f01601f191660200182016040528015612b0c576020820181803683370190505b509250600091505b60ff82165b8351811015612b5f57612b348360ff16820360020187613809565b848281518110612b4057fe5b60200101906001600160f81b031916908160001a905350600101612b19565b50505092915050565b600061227282600001516009815181106129e857fe5b612b8661410b565b612b9a82600001516006815181106129c557fe5b6020820152612ba761414c565b612bb48260200151613632565b9050612bbf81613866565b15612bd457612bcd81613657565b8252612c54565b602082015180516060906000190167ffffffffffffffff81118015612bf857600080fd5b506040519080825280601f01601f191660200182016040528015612c23576020820181803683370190505b509050600080836021019150826020019050612c41828285516138a0565b612c4d61299584613632565b8652505050505b612c5d83612b68565b604083015250919050565b612c7061412c565b612c7861414c565b612c998360000151600381518110612c8c57fe5b6020026020010151613657565b836040015181518110612ca857fe5b602002602001015190506040518060400160405280828152602001612ccc83613657565b90529392505050565b60006122728260200151600081518110612ceb57fe5b60200260200101516138eb565b600061227282600001516008815181106129e857fe5b6020015190565b606061227282600001516007815181106129c557fe5b600061227282600001516005815181106129e857fe5b6000612d4b61414c565b612d5484613632565b90506060612d6182613657565b905060608085600082612d738b6129f5565b9050805160001415612d8f576000975050505050505050612f80565b60005b8651811015612f77578151831115612db557600098505050505050505050612f80565b612dd1878281518110612dc457fe5b6020026020010151613905565b955085805190602001208414612df257600098505050505050505050612f80565b612e01878281518110612c8c57fe5b9450845160111415612ebe578151831415612e5d578c80519060200120612e2e866010815181106129c557fe5b805190602001201415612e4c57600198505050505050505050612f80565b600098505050505050505050612f80565b6000828481518110612e6b57fe5b016020015160f81c90506010811115612e905760009950505050505050505050612f80565b612eaf868260ff1681518110612ea257fe5b6020026020010151613984565b94505060019290920191612f6f565b845160021415612e4c576000612ee4612edd876000815181106129c557fe5b84866139a1565b905082518185011415612f3a578d80519060200120612f09876001815181106129c557fe5b805190602001201415612f285760019950505050505050505050612f80565b60009950505050505050505050612f80565b80612f515760009950505050505050505050612f80565b8084019350612f6686600181518110612ea257fe5b9450612f6f9050565b600101612d92565b50505050505050505b949350505050565b600061227282600001516003815181106129e857fe5b600061227282600001516004815181106129e857fe5b600061227282600001516000815181106129e857fe5b606061227282600001516001815181106129c557fe5b600854604080516320a9cea560e11b81526004810185905290516000928392839283926001600160a01b0316916341539d4a9160248083019260a0929190829003018186803b15801561303257600080fd5b505afa158015613046573d6000803e3d6000fd5b505050506040513d60a081101561305c57600080fd5b508051602082015160609092015190945090925090506130cb6130858b8463ffffffff613a8216565b6040805160208082018f90528183018e9052606082018d905260808083018d90528351808403909101815260a0909201909252805191012090858863ffffffff613adf16565b6131065760405162461bcd60e51b81526004018080602001828103825260268152602001806143af6026913960400191505060405180910390fd5b9998505050505050505050565b60606122728260000151613905565b606061313061299583613632565b9050606061314482600181518110612c8c57fe5b90507fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60001b61317a826000815181106129e857fe5b146131b65760405162461bcd60e51b815260040180806020018281038252602981526020018061444f6029913960400191505060405180910390fd5b60006131c8826001815181106129e857fe5b905060006001600160a01b03166131e5836002815181106129e857fe5b6001600160a01b03161461322a5760405162461bcd60e51b81526004018080602001828103825260288152602001806144a26028913960400191505060405180910390fd5b600061323c846002815181106129e857fe5b9050600061324a8783611762565b90506114516001600160a01b038816848363ffffffff613c3516565b6000816132ae576040805162461bcd60e51b81526020600482015260116024820152700703237206469766973696f6e206279203607c1b604482015290519081900360640190fd5b6b033b2e3c9fd0803ce80000008381029081048414613314576040805162461bcd60e51b815260206004820152601b60248201527f703237206d756c7469706c69636174696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60028304908101908082101561335b5760405162461bcd60e51b81526004018080602001828103825260248152602001806142bc6024913960400191505060405180910390fd5b83828161336457fe5b0495945050505050565b600082820280613382576000915050612272565b83818161338b57fe5b0483146133df576040805162461bcd60e51b815260206004820152601b60248201527f703237206d756c7469706c69636174696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6b019d971e4fe8401e740000009081019081101561342e5760405162461bcd60e51b81526004018080602001828103825260248152602001806142bc6024913960400191505060405180910390fd5b6b033b2e3c9fd0803ce800000090049392505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611037908590613c83565b600060405180608001604052806043815260200161419660439139805190602001208260000151836020015184604001518051906020012060405160200180858152602001848152602001836001600160a01b03166001600160a01b03168152602001828152602001945050505050604051602081830303815290604052805190602001209050919050565b600061353461103d565b82604051602001808061190160f01b81525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050919050565b6040518060800160405280604f8152602001614247604f913980516020918201208251838301206040805180820190915260018152603160f81b930192909252907fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6306135e161116a565b604080516020808201979097528082019590955260608501939093526001600160a01b03909116608084015260a0808401919091528151808403909101815260c09092019052805191012060025550565b61363a61414c565b506040805180820190915281518152602082810190820152919050565b606061366282613866565b61366b57600080fd5b600061367683613d34565b905060608167ffffffffffffffff8111801561369157600080fd5b506040519080825280602002602001820160405280156136cb57816020015b6136b861414c565b8152602001906001900390816136b05790505b50905060006136dd8560200151613d90565b60208601510190506000805b84811015613734576136fa83613df3565b915060405180604001604052808381526020018481525084828151811061371d57fe5b6020908102919091010152918101916001016136e9565b509195945050505050565b805160609061374d57600080fd5b60008061375984613e87565b9150915060608167ffffffffffffffff8111801561377657600080fd5b506040519080825280601f01601f1916602001820160405280156137a1576020820181803683370190505b509050602081016137b3848285613ead565b50949350505050565b8051600090158015906137d157508151602110155b6137da57600080fd5b6000806137e684613e87565b815191935091506020821015612f805760208290036101000a9004949350505050565b6000600283061561383a57601082600285048151811061382557fe5b016020015160f81c8161383457fe5b0661385c565b601082600285048151811061384b57fe5b016020015160f81c8161385a57fe5b045b60f81b9392505050565b8051600090613877575060006114c9565b6020820151805160001a9060c0821015613896576000925050506114c9565b5060019392505050565b806138aa576120d5565b5b602081106138ca578251825260209283019290910190601f19016138ab565b915181516020939093036101000a6000190180199091169216919091179052565b80516000906015146138fc57600080fd5b612272826137bc565b606080826000015167ffffffffffffffff8111801561392357600080fd5b506040519080825280601f01601f19166020018201604052801561394e576020820181803683370190505b5090508051600014156139625790506114c9565b600081602001905061397d8460200151828660000151613ead565b5092915050565b805160009060211461399557600080fd5b50602001516001015190565b60008060606139af866129f5565b90506060815167ffffffffffffffff811180156139cb57600080fd5b506040519080825280601f01601f1916602001820160405280156139f6576020820181803683370190505b509050845b82518601811015613a50576000878281518110613a1457fe5b602001015160f81c60f81b9050808388840381518110613a3057fe5b60200101906001600160f81b031916908160001a905350506001016139fb565b50808051906020012082805190602001201415613a705781519250613a75565b600092505b50909150505b9392505050565b600082821115613ad9576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60006020825181613aec57fe5b0615613b36576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e0e4dedecc40d8cadccee8d60631b604482015290519081900360640190fd5b60006020835181613b4357fe5b0490508060020a8510613b95576040805162461bcd60e51b81526020600482015260156024820152744c65616620696e64657820697320746f6f2062696760581b604482015290519081900360640190fd5b60008660205b85518111613c275785810151925060028806613be75781836040516020018083815260200182815260200192505050604051602081830303815290604052805190602001209150613c19565b828260405160200180838152602001828152602001925050506040516020818303038152906040528051906020012091505b600288049750602001613b9b565b509094149695505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526120d59084905b6060613cd8826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613efe9092919063ffffffff16565b8051909150156120d557808060200190516020811015613cf757600080fd5b50516120d55760405162461bcd60e51b815260040180806020018281038252602a815260200180614478602a913960400191505060405180910390fd5b8051600090613d45575060006114c9565b60008090506000613d598460200151613d90565b602085015185519181019250015b80821015613d8757613d7882613df3565b60019093019290910190613d67565b50909392505050565b8051600090811a6080811015613daa5760009150506114c9565b60b8811080613dc5575060c08110801590613dc5575060f881105b15613dd45760019150506114c9565b60c0811015613de85760b5190190506114c9565b60f5190190506114c9565b80516000908190811a6080811015613e0e576001915061397d565b60b8811015613e2357607e198101915061397d565b60c0811015613e505760b78103600185019450806020036101000a8551046001820181019350505061397d565b60f8811015613e655760be198101915061397d565b60019390930151602084900360f7016101000a900490920160f5190192915050565b6000806000613e998460200151613d90565b602085015194519481019594039392505050565b80613eb7576120d5565b5b60208110613ed7578251825260209283019290910190601f1901613eb8565b80156120d557915181516020939093036101000a6000190180199091169216919091179052565b6060612f80848460008585613f1285614024565b613f63576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310613fa25780518252601f199092019160209182019101613f83565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114614004576040519150601f19603f3d011682016040523d82523d6000602084013e614009565b606091505b509150915061401982828661402a565b979650505050505050565b3b151590565b60608315614039575081613a7b565b8251156140495782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561409357818101518382015260200161407b565b50505050905090810190601f1680156140c05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b60405180606001604052806000815260200160006001600160a01b03168152602001606081525090565b6040518060200160405280606081525090565b60405180606001604052806060815260200160608152602001600081525090565b604051806040016040528061413f61414c565b8152602001606081525090565b60405180604001604052806000815260200160008152509056fe41546f6b656e526f6f74436861696e4d616e616765723a204368696c6420746f6b656e206973207468652073616d654d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e61747572652941546f6b656e526f6f74436861696e4d616e616765723a20544f4b454e5f4e4f545f4d415050454443616e6e6f742073656e6420455448206f7665722061546f6b656e2062726964676541546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f55534552454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c6164647265737320766572696679696e67436f6e74726163742c627974657333322073616c742941546f6b656e526f6f74436861696e4d616e616765723a20414c52454144595f4d4150504544703237206d756c7469706c69636174696f6e206164646974696f6e206f766572666c6f7741546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f50524f4f464e61746976654d6574615472616e73616374696f6e3a20494e56414c49445f5349474e455241546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f4252414e43485f4d41534b41546f6b656e526f6f74436861696e4d616e616765723a20455849545f414c52454144595f50524f434553534544526f6f74436861696e4d616e616765723a204241445f4e45575f434845434b504f494e545f4d414e4147455241546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f4845414445525369676e657220616e64207369676e617475726520646f206e6f74206d61746368526f6f74436861696e4d616e616765723a204241445f4e45575f53544154455f53454e44455241546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f4348494c445f434841494e5f4144445245535341546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f5349474e41545552455361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656441546f6b656e526f6f74436861696e4d616e616765723a20494e56414c49445f5245434549564552a264697066735822122037454f12bec2f2dc5b85f7a30be5e9fa05dca30edf2849f968433600081f42ca64736f6c63430006060033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 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.