Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
107556619 | 537 days ago | 0 ETH | ||||
107556619 | 537 days ago | 0 ETH | ||||
107555310 | 537 days ago | 0 ETH | ||||
107555310 | 537 days ago | 0 ETH | ||||
107554234 | 537 days ago | 0 ETH | ||||
107554234 | 537 days ago | 0 ETH | ||||
107552809 | 537 days ago | 0 ETH | ||||
107552809 | 537 days ago | 0 ETH | ||||
107552446 | 537 days ago | 0 ETH | ||||
107552446 | 537 days ago | 0 ETH | ||||
107552178 | 537 days ago | 0 ETH | ||||
107552178 | 537 days ago | 0 ETH | ||||
107551918 | 537 days ago | 0 ETH | ||||
107551918 | 537 days ago | 0 ETH | ||||
107550805 | 537 days ago | 0 ETH | ||||
107550805 | 537 days ago | 0 ETH | ||||
107550606 | 537 days ago | 0 ETH | ||||
107550606 | 537 days ago | 0 ETH | ||||
107550606 | 537 days ago | 0 ETH | ||||
107550606 | 537 days ago | 0 ETH | ||||
107548853 | 537 days ago | 0 ETH | ||||
107548853 | 537 days ago | 0 ETH | ||||
107548853 | 537 days ago | 0 ETH | ||||
107548853 | 537 days ago | 0 ETH | ||||
107541769 | 538 days ago | 0 ETH |
Loading...
Loading
Contract Name:
VotingEscrowStateOracle
Compiler Version
v0.8.12+commit.f00d7308
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.12; import {RLPReader} from "RLPReader.sol"; import {StateProofVerifier as Verifier} from "StateProofVerifier.sol"; interface AnyCallProxy { function context() external view returns(address, uint256); } contract VotingEscrowStateOracle { using RLPReader for bytes; using RLPReader for RLPReader.RLPItem; struct LockedBalance { int128 amount; uint256 end; } struct Point { int128 bias; int128 slope; uint256 ts; uint256 blk; } /// Address of the voting escrow contract on Ethereum address constant VOTING_ESCROW = 0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2; /// Hash of the voting escrow contract address bytes32 constant VOTING_ESCROW_HASH = keccak256(abi.encodePacked(VOTING_ESCROW)); /// `VotingEscrow.epoch()` storage slot hash bytes32 constant EPOCH_HASH = keccak256(abi.encode(3)); /// Hash of the block header for the Ethereum genesis block bytes32 constant GENESIS_BLOCKHASH = 0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3; /// Week in seconds uint256 constant WEEK = 1 weeks; /// Address of the AnyCallProxy for the chain this contract is deployed on address public immutable ANYCALL; /// Mapping of Ethereum block number to blockhash mapping(uint256 => bytes32) private _eth_blockhash; /// Last Ethereum block number which had its blockhash stored uint256 public last_eth_block_number; /// Owner of the contract with special privileges address public owner; /// Future owner of the contract address public future_owner; /// Migrated `VotingEscrow` storage variables uint256 public epoch; Point[100000000000000000000000000000] public point_history; mapping(address => uint256) public user_point_epoch; mapping(address => Point[1000000000]) public user_point_history; mapping(uint256 => int128) public slope_changes; mapping(address => LockedBalance) public locked; mapping(bytes32 => bool) public submitted_hashes; /// Log a blockhash update event SetBlockhash(uint256 _eth_block_number, bytes32 _eth_blockhash); /// Log a transfer of ownership event TransferOwnership(address _old_owner, address _new_owner); /// Log a proof submission event SubmittedState(address _user, bytes32 blockhash, bytes32 proofhash); constructor(address _anycall) { _eth_blockhash[0] = GENESIS_BLOCKHASH; emit SetBlockhash(0, GENESIS_BLOCKHASH); // Mar-02-2022 07:06:57 PM +UTC _eth_blockhash[14309414] = 0xa460e43297d3f7a92ee5dd34ee39a20b941dfc805a7dbfa99e892214d5da026c; emit SetBlockhash(14309414, 0xa460e43297d3f7a92ee5dd34ee39a20b941dfc805a7dbfa99e892214d5da026c); last_eth_block_number = 14309414; owner = msg.sender; emit TransferOwnership(address(0), msg.sender); ANYCALL = _anycall; } function balanceOf(address _user) external view returns(uint256) { return balanceOf(_user, block.timestamp); } function balanceOf(address _user, uint256 _timestamp) public view returns(uint256) { uint256 _epoch = user_point_epoch[_user]; if (_epoch == 0) { return 0; } Point memory last_point = user_point_history[_user][_epoch]; last_point.bias -= last_point.slope * abi.decode(abi.encode(_timestamp - last_point.ts), (int128)); if (last_point.bias < 0) { return 0; } return abi.decode(abi.encode(last_point.bias), (uint256)); } function totalSupply() external view returns(uint256) { return totalSupply(block.timestamp); } function totalSupply(uint256 _timestamp) public view returns(uint256) { Point memory last_point = point_history[epoch]; uint256 t_i = (last_point.ts / WEEK) * WEEK; // value in the past for (uint256 i = 0; i < 255; i++) { t_i += WEEK; // + week int128 d_slope = 0; if (t_i > _timestamp) { t_i = _timestamp; } else { d_slope = slope_changes[t_i]; if (d_slope == 0) { break; } } last_point.bias -= last_point.slope * abi.decode(abi.encode(t_i - last_point.ts), (int128)); if (t_i == _timestamp) { break; } last_point.slope += d_slope; last_point.ts = t_i; } if (last_point.bias < 0) { return 0; } return abi.decode(abi.encode(last_point.bias), (uint256)); } function submit_state(address _user, bytes memory _block_header_rlp, bytes memory _proof_rlp) external { // verify block header Verifier.BlockHeader memory block_header = Verifier.parseBlockHeader(_block_header_rlp); require(block_header.hash != bytes32(0)); // dev: invalid blockhash require(block_header.hash == _eth_blockhash[block_header.number]); // dev: blockhash mismatch // convert _proof_rlp into a list of `RLPItem`s RLPReader.RLPItem[] memory proofs = _proof_rlp.toRlpItem().toList(); require(proofs.length == 21); // dev: invalid number of proofs // 0th proof is the account proof for Voting Escrow contract Verifier.Account memory ve_account = Verifier.extractAccountFromProof( VOTING_ESCROW_HASH, // position of the account is the hash of its address block_header.stateRootHash, proofs[0].toList() ); require(ve_account.exists); // dev: Voting Escrow account does not exist // 1st proof is the `VotingEscrow.epoch()` storage slot proof Verifier.SlotValue memory slot_epoch = Verifier.extractSlotValueFromProof( EPOCH_HASH, ve_account.storageRoot, proofs[1].toList() ); require(slot_epoch.exists); // 2-5th proof are the `VotingEscrow.point_history(uint256)` slots // this is a struct where bias and slope are int128, the position is determined based // on the value of `epoch` Verifier.SlotValue[4] memory slot_point_history; for (uint256 i = 0; i < 4; i++) { slot_point_history[i] = Verifier.extractSlotValueFromProof( keccak256(abi.encode(uint256(keccak256(abi.encode(uint256(keccak256(abi.encode(4))) + slot_epoch.value))) + i)), ve_account.storageRoot, proofs[2 + i].toList() ); require(slot_point_history[i].exists); // dev: slot does not exist } // 6th proof is the `VotingEscrow.user_point_epoch(address)` slot proof Verifier.SlotValue memory slot_user_point_epoch = Verifier.extractSlotValueFromProof( keccak256(abi.encode(keccak256(abi.encode(6, _user)))), ve_account.storageRoot, proofs[6].toList() ); require(slot_user_point_epoch.exists); // dev: slot does not exist // 7-10th proof are for `VotingEscrow.user_point_history` slots // similar to `point_history` this is a struct Verifier.SlotValue[4] memory slot_user_point_history; for (uint256 i = 0; i < 4; i++) { slot_user_point_history[i] = Verifier.extractSlotValueFromProof( keccak256(abi.encode(uint256(keccak256(abi.encode(uint256(keccak256(abi.encode(keccak256(abi.encode(5, _user))))) + slot_user_point_epoch.value))) + i)), ve_account.storageRoot, proofs[7 + i].toList() ); require(slot_user_point_history[i].exists); // dev: slot does not exist } // 11-12th proof are for `VotingEscrow.locked()` this is a struct with 2 members Verifier.SlotValue[2] memory slot_locked; for (uint256 i = 0; i < 2; i++) { slot_locked[i] = Verifier.extractSlotValueFromProof( keccak256(abi.encode(uint256(keccak256(abi.encode(keccak256(abi.encode(2, _user))))) + i)), ve_account.storageRoot, proofs[11 + i].toList() ); require(slot_locked[i].exists); // dev: slot does not exist } // Remaining proofs are for 2 months worth of slope changes // starting from the week beginning the last global point Verifier.SlotValue[8] memory slot_slope_changes; uint256 start_time = (slot_point_history[2].value / WEEK) * WEEK + WEEK; for (uint256 i = 0; i < 8; i++) { slot_slope_changes[i] = Verifier.extractSlotValueFromProof( keccak256(abi.encode(keccak256(abi.encode(7, start_time + WEEK * i)))), ve_account.storageRoot, proofs[13 + i].toList() ); require(slot_slope_changes[i].exists); // dev: slot does not exist } { /// incrememt the epoch storage var only if fresh /// also update slope changes too if (slot_epoch.value > epoch) { epoch = slot_epoch.value; for (uint256 i = 0; i < 8; i++) { slope_changes[start_time + WEEK * i] = abi.decode(abi.encode(slot_slope_changes[i].value), (int128)); } } /// always set the point_history structs point_history[slot_epoch.value] = Point( abi.decode(abi.encode(slot_point_history[0].value), (int128)), // bias abi.decode(abi.encode(slot_point_history[1].value), (int128)), // slope slot_point_history[2].value, // ts slot_point_history[3].value // blk ); // update the user point epoch and locked balance if it is newer if (slot_user_point_epoch.value > user_point_epoch[_user]) { user_point_epoch[_user] = slot_user_point_epoch.value; locked[_user] = LockedBalance( abi.decode(abi.encode(slot_locked[0].value), (int128)), slot_locked[1].value ); } /// always set the point_history structs user_point_history[_user][slot_user_point_epoch.value] = Point( abi.decode(abi.encode(slot_user_point_history[0].value), (int128)), // bias abi.decode(abi.encode(slot_user_point_history[1].value), (int128)), // slope slot_user_point_history[2].value, // ts slot_user_point_history[3].value // blk ); } emit SubmittedState(_user, block_header.hash, keccak256(_proof_rlp)); } /** * @notice Get the Ethereum blockhash for block number `_eth_block_number` * @dev Reverts if the blockhash is unavailable, value in storage is `bytes32(0)` * @param _eth_block_number The block number to query the blockhash of * @return eth_blockhash The blockhash of `_eth_block_number` */ function get_eth_blockhash(uint256 _eth_block_number) external view returns(bytes32 eth_blockhash) { eth_blockhash = _eth_blockhash[_eth_block_number]; require(eth_blockhash != bytes32(0)); // dev: blockhash unavailable } /** * @notice Set the Ethereum blockhash for `_eth_block_number` in storage * @param _eth_block_number The block number to set the blockhash of * @param __eth_blockhash The blockhash to set in storage */ function set_eth_blockhash(uint256 _eth_block_number, bytes32 __eth_blockhash) external { // either a cross-chain call from `self` or `owner` is valid to set the blockhash if (msg.sender == ANYCALL) { (address sender, uint256 from_chain_id) = AnyCallProxy(msg.sender).context(); require(sender == address(this) && from_chain_id == 1); // dev: only root self } else { require(msg.sender == owner); // dev: only owner } // set the blockhash in storage _eth_blockhash[_eth_block_number] = __eth_blockhash; emit SetBlockhash(_eth_block_number, __eth_blockhash); // update the last block number stored if (_eth_block_number > last_eth_block_number) { last_eth_block_number = _eth_block_number; } } /** * @notice Commit the future owner to storage for later transfer to * @param _future_owner The address of the future owner */ function commit_transfer_ownership(address _future_owner) external { require(msg.sender == owner); // dev: only owner future_owner = _future_owner; } /** * @notice Accept the transfer of ownership * @dev Only callable by the future owner */ function accept_transfer_ownership() external { require(msg.sender == future_owner); // dev: only future owner emit TransferOwnership(owner, msg.sender); owner = msg.sender; } }
// SPDX-License-Identifier: Apache-2.0 /* * @author Hamdi Allam [email protected] * Please reach out with any questions or concerns */ pragma solidity >=0.8.12; 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(uint160(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)) } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.12; import {RLPReader} from "RLPReader.sol"; import {MerklePatriciaProofVerifier} from "MerklePatriciaProofVerifier.sol"; /** * @title A helper library for verification of Merkle Patricia account and state proofs. */ library StateProofVerifier { using RLPReader for RLPReader.RLPItem; using RLPReader for bytes; uint256 constant HEADER_STATE_ROOT_INDEX = 3; uint256 constant HEADER_NUMBER_INDEX = 8; uint256 constant HEADER_TIMESTAMP_INDEX = 11; struct BlockHeader { bytes32 hash; bytes32 stateRootHash; uint256 number; uint256 timestamp; } struct Account { bool exists; uint256 nonce; uint256 balance; bytes32 storageRoot; bytes32 codeHash; } struct SlotValue { bool exists; uint256 value; } /** * @notice Parses block header and verifies its presence onchain within the latest 256 blocks. * @param _headerRlpBytes RLP-encoded block header. */ function verifyBlockHeader(bytes memory _headerRlpBytes) internal view returns (BlockHeader memory) { BlockHeader memory header = parseBlockHeader(_headerRlpBytes); // ensure that the block is actually in the blockchain require(header.hash == blockhash(header.number), "blockhash mismatch"); return header; } /** * @notice Parses RLP-encoded block header. * @param _headerRlpBytes RLP-encoded block header. */ function parseBlockHeader(bytes memory _headerRlpBytes) internal pure returns (BlockHeader memory) { BlockHeader memory result; RLPReader.RLPItem[] memory headerFields = _headerRlpBytes.toRlpItem().toList(); require(headerFields.length > HEADER_TIMESTAMP_INDEX); result.stateRootHash = bytes32(headerFields[HEADER_STATE_ROOT_INDEX].toUint()); result.number = headerFields[HEADER_NUMBER_INDEX].toUint(); result.timestamp = headerFields[HEADER_TIMESTAMP_INDEX].toUint(); result.hash = keccak256(_headerRlpBytes); return result; } /** * @notice Verifies Merkle Patricia proof of an account and extracts the account fields. * * @param _addressHash Keccak256 hash of the address corresponding to the account. * @param _stateRootHash MPT root hash of the Ethereum state trie. */ function extractAccountFromProof( bytes32 _addressHash, // keccak256(abi.encodePacked(address)) bytes32 _stateRootHash, RLPReader.RLPItem[] memory _proof ) internal pure returns (Account memory) { bytes memory acctRlpBytes = MerklePatriciaProofVerifier.extractProofValue( _stateRootHash, abi.encodePacked(_addressHash), _proof ); Account memory account; if (acctRlpBytes.length == 0) { return account; } RLPReader.RLPItem[] memory acctFields = acctRlpBytes.toRlpItem().toList(); require(acctFields.length == 4); account.exists = true; account.nonce = acctFields[0].toUint(); account.balance = acctFields[1].toUint(); account.storageRoot = bytes32(acctFields[2].toUint()); account.codeHash = bytes32(acctFields[3].toUint()); return account; } /** * @notice Verifies Merkle Patricia proof of a slot and extracts the slot's value. * * @param _slotHash Keccak256 hash of the slot position. * @param _storageRootHash MPT root hash of the account's storage trie. */ function extractSlotValueFromProof( bytes32 _slotHash, bytes32 _storageRootHash, RLPReader.RLPItem[] memory _proof ) internal pure returns (SlotValue memory) { bytes memory valueRlpBytes = MerklePatriciaProofVerifier.extractProofValue( _storageRootHash, abi.encodePacked(_slotHash), _proof ); SlotValue memory value; if (valueRlpBytes.length != 0) { value.exists = true; value.value = valueRlpBytes.toRlpItem().toUint(); } return value; } }
// SPDX-License-Identifier: MIT /** * Copied from https://github.com/lorenzb/proveth/blob/c74b20e/onchain/ProvethVerifier.sol * with minor performance and code style-related modifications. */ pragma solidity >=0.8.12; import {RLPReader} from "RLPReader.sol"; library MerklePatriciaProofVerifier { using RLPReader for RLPReader.RLPItem; using RLPReader for bytes; /// @dev Validates a Merkle-Patricia-Trie proof. /// If the proof proves the inclusion of some key-value pair in the /// trie, the value is returned. Otherwise, i.e. if the proof proves /// the exclusion of a key from the trie, an empty byte array is /// returned. /// @param rootHash is the Keccak-256 hash of the root node of the MPT. /// @param path is the key of the node whose inclusion/exclusion we are /// proving. /// @param stack is the stack of MPT nodes (starting with the root) that /// need to be traversed during verification. /// @return value whose inclusion is proved or an empty byte array for /// a proof of exclusion function extractProofValue( bytes32 rootHash, bytes memory path, RLPReader.RLPItem[] memory stack ) internal pure returns (bytes memory value) { bytes memory mptKey = _decodeNibbles(path, 0); uint256 mptKeyOffset = 0; bytes32 nodeHashHash; RLPReader.RLPItem[] memory node; RLPReader.RLPItem memory rlpValue; if (stack.length == 0) { // Root hash of empty Merkle-Patricia-Trie require(rootHash == 0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421); return new bytes(0); } // Traverse stack of nodes starting at root. for (uint256 i = 0; i < stack.length; i++) { // We use the fact that an rlp encoded list consists of some // encoding of its length plus the concatenation of its // *rlp-encoded* items. // The root node is hashed with Keccak-256 ... if (i == 0 && rootHash != stack[i].rlpBytesKeccak256()) { revert(); } // ... whereas all other nodes are hashed with the MPT // hash function. if (i != 0 && nodeHashHash != _mptHashHash(stack[i])) { revert(); } // We verified that stack[i] has the correct hash, so we // may safely decode it. node = stack[i].toList(); if (node.length == 2) { // Extension or Leaf node bool isLeaf; bytes memory nodeKey; (isLeaf, nodeKey) = _merklePatriciaCompactDecode(node[0].toBytes()); uint256 prefixLength = _sharedPrefixLength(mptKeyOffset, mptKey, nodeKey); mptKeyOffset += prefixLength; if (prefixLength < nodeKey.length) { // Proof claims divergent extension or leaf. (Only // relevant for proofs of exclusion.) // An Extension/Leaf node is divergent iff it "skips" over // the point at which a Branch node should have been had the // excluded key been included in the trie. // Example: Imagine a proof of exclusion for path [1, 4], // where the current node is a Leaf node with // path [1, 3, 3, 7]. For [1, 4] to be included, there // should have been a Branch node at [1] with a child // at 3 and a child at 4. // Sanity check if (i < stack.length - 1) { // divergent node must come last in proof revert(); } return new bytes(0); } if (isLeaf) { // Sanity check if (i < stack.length - 1) { // leaf node must come last in proof revert(); } if (mptKeyOffset < mptKey.length) { return new bytes(0); } rlpValue = node[1]; return rlpValue.toBytes(); } else { // extension // Sanity check if (i == stack.length - 1) { // shouldn't be at last level revert(); } if (!node[1].isList()) { // rlp(child) was at least 32 bytes. node[1] contains // Keccak256(rlp(child)). nodeHashHash = node[1].payloadKeccak256(); } else { // rlp(child) was less than 32 bytes. node[1] contains // rlp(child). nodeHashHash = node[1].rlpBytesKeccak256(); } } } else if (node.length == 17) { // Branch node if (mptKeyOffset != mptKey.length) { // we haven't consumed the entire path, so we need to look at a child uint8 nibble = uint8(mptKey[mptKeyOffset]); mptKeyOffset += 1; if (nibble >= 16) { // each element of the path has to be a nibble revert(); } if (_isEmptyBytesequence(node[nibble])) { // Sanity if (i != stack.length - 1) { // leaf node should be at last level revert(); } return new bytes(0); } else if (!node[nibble].isList()) { nodeHashHash = node[nibble].payloadKeccak256(); } else { nodeHashHash = node[nibble].rlpBytesKeccak256(); } } else { // we have consumed the entire mptKey, so we need to look at what's contained in this node. // Sanity if (i != stack.length - 1) { // should be at last level revert(); } return node[16].toBytes(); } } } } /// @dev Computes the hash of the Merkle-Patricia-Trie hash of the RLP item. /// Merkle-Patricia-Tries use a weird "hash function" that outputs /// *variable-length* hashes: If the item is shorter than 32 bytes, /// the MPT hash is the item. Otherwise, the MPT hash is the /// Keccak-256 hash of the item. /// The easiest way to compare variable-length byte sequences is /// to compare their Keccak-256 hashes. /// @param item The RLP item to be hashed. /// @return Keccak-256(MPT-hash(item)) function _mptHashHash(RLPReader.RLPItem memory item) private pure returns (bytes32) { if (item.len < 32) { return item.rlpBytesKeccak256(); } else { return keccak256(abi.encodePacked(item.rlpBytesKeccak256())); } } function _isEmptyBytesequence(RLPReader.RLPItem memory item) private pure returns (bool) { if (item.len != 1) { return false; } uint8 b; uint256 memPtr = item.memPtr; assembly { b := byte(0, mload(memPtr)) } return b == 0x80 /* empty byte string */; } function _merklePatriciaCompactDecode(bytes memory compact) private pure returns (bool isLeaf, bytes memory nibbles) { require(compact.length > 0); uint256 first_nibble = uint8(compact[0]) >> 4 & 0xF; uint256 skipNibbles; if (first_nibble == 0) { skipNibbles = 2; isLeaf = false; } else if (first_nibble == 1) { skipNibbles = 1; isLeaf = false; } else if (first_nibble == 2) { skipNibbles = 2; isLeaf = true; } else if (first_nibble == 3) { skipNibbles = 1; isLeaf = true; } else { // Not supposed to happen! revert(); } return (isLeaf, _decodeNibbles(compact, skipNibbles)); } function _decodeNibbles(bytes memory compact, uint256 skipNibbles) private pure returns (bytes memory nibbles) { require(compact.length > 0); uint256 length = compact.length * 2; require(skipNibbles <= length); length -= skipNibbles; nibbles = new bytes(length); uint256 nibblesLength = 0; for (uint256 i = skipNibbles; i < skipNibbles + length; i += 1) { if (i % 2 == 0) { nibbles[nibblesLength] = bytes1((uint8(compact[i/2]) >> 4) & 0xF); } else { nibbles[nibblesLength] = bytes1((uint8(compact[i/2]) >> 0) & 0xF); } nibblesLength += 1; } assert(nibblesLength == nibbles.length); } function _sharedPrefixLength(uint256 xsOffset, bytes memory xs, bytes memory ys) private pure returns (uint256) { uint256 i; for (i = 0; i + xsOffset < xs.length && i < ys.length; i++) { if (xs[i + xsOffset] != ys[i]) { return i; } } return i; } }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "VotingEscrowStateOracle.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_anycall","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_eth_block_number","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"_eth_blockhash","type":"bytes32"}],"name":"SetBlockhash","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_user","type":"address"},{"indexed":false,"internalType":"bytes32","name":"blockhash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"proofhash","type":"bytes32"}],"name":"SubmittedState","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_old_owner","type":"address"},{"indexed":false,"internalType":"address","name":"_new_owner","type":"address"}],"name":"TransferOwnership","type":"event"},{"inputs":[],"name":"ANYCALL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accept_transfer_ownership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_future_owner","type":"address"}],"name":"commit_transfer_ownership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"future_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_eth_block_number","type":"uint256"}],"name":"get_eth_blockhash","outputs":[{"internalType":"bytes32","name":"eth_blockhash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"last_eth_block_number","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"locked","outputs":[{"internalType":"int128","name":"amount","type":"int128"},{"internalType":"uint256","name":"end","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_eth_block_number","type":"uint256"},{"internalType":"bytes32","name":"__eth_blockhash","type":"bytes32"}],"name":"set_eth_blockhash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"slope_changes","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"bytes","name":"_block_header_rlp","type":"bytes"},{"internalType":"bytes","name":"_proof_rlp","type":"bytes"}],"name":"submit_state","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"submitted_hashes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"user_point_epoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"user_point_history","outputs":[{"internalType":"int128","name":"bias","type":"int128"},{"internalType":"int128","name":"slope","type":"int128"},{"internalType":"uint256","name":"ts","type":"uint256"},{"internalType":"uint256","name":"blk","type":"uint256"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162002ba338038062002ba38339810160408190526200003491620001b3565b600080805260208181527fd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa37fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb581905560408051938452918301527fe16e73e811796e9411f8c58ddf002de2c1e383ecaca4d22e1ddb14cdd0e514ab910160405180910390a162da582660008181526020527fa460e43297d3f7a92ee5dd34ee39a20b941dfc805a7dbfa99e892214d5da026c7fde2865133d9101d266d37bb7025fc43ad6eaa4790f10bb26362c4c3becd4d5438190556040517fe16e73e811796e9411f8c58ddf002de2c1e383ecaca4d22e1ddb14cdd0e514ab926200014292908252602082015260400190565b60405180910390a162da5826600155600280546001600160a01b03191633908117909155604080516000815260208101929092527f5c486528ec3e3f0ea91181cff8116f02bfa350e03b8b6f12e00765adbb5af85c910160405180910390a16001600160a01b0316608052620001e5565b600060208284031215620001c657600080fd5b81516001600160a01b0381168114620001de57600080fd5b9392505050565b60805161299b62000208600039600081816101e20152611009015261299b6000f3fe608060405234801561001057600080fd5b506004361061012b5760003560e01c806370a08231116100ad578063bd85b03911610071578063bd85b0391461030b578063cbf9fe5f1461031e578063d1febfb914610372578063e4160ddb14610385578063e5ea47b81461039857600080fd5b806370a082311461029157806371197484146102a45780638da5cb5b146102e6578063900cf0cf146102f9578063aa34453f1461030257600080fd5b80631ec0cdc1116100f45780631ec0cdc1146101b25780632090356b146101dd57806328d09d47146102045780633fb9fbd51461023f5780636b441a401461027e57600080fd5b8062fdd58e14610130578063010ae75714610156578063068b4668146101825780630fb997cc1461019757806318160ddd146101aa575b600080fd5b61014361013e366004612425565b6103a0565b6040519081526020015b60405180910390f35b610143610164366004612451565b6c03c95a2f0b4856475fe00000056020526000908152604090205481565b610195610190366004612511565b61050a565b005b6101956101a5366004612587565b610ffe565b610143611134565b6003546101c5906001600160a01b031681565b6040516001600160a01b03909116815260200161014d565b6101c57f000000000000000000000000000000000000000000000000000000000000000081565b610217610212366004612425565b611144565b60408051600f95860b81529390940b602084015292820152606081019190915260800161014d565b61026e61024d3660046125a9565b6c03c95a2f0b4856475fe00000096020526000908152604090205460ff1681565b604051901515815260200161014d565b61019561028c366004612451565b611197565b61014361029f366004612451565b6111d0565b6102d36102b23660046125a9565b6c03c95a2f0b4856475fe000000760205260009081526040902054600f0b81565b604051600f9190910b815260200161014d565b6002546101c5906001600160a01b031681565b61014360045481565b61014360015481565b6101436103193660046125a9565b6111dc565b61035861032c366004612451565b6c03c95a2f0b4856475fe00000086020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b835260208301919091520161014d565b6102176103803660046125a9565b6113b6565b6101436103933660046125a9565b6113fa565b610195611418565b6001600160a01b03821660009081526c03c95a2f0b4856475fe00000056020526040812054806103d4576000915050610504565b6001600160a01b03841660009081526c03c95a2f0b4856475fe00000066020526040812082633b9aca00811061040c5761040c6125c2565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201839052600201546060820152915061045890856125ee565b60405160200161046a91815260200190565b60405160208183030381529060405280602001905181019061048c9190612605565b816020015161049b9190612628565b815182906104aa9083906126c6565b600f90810b90915282516000910b121590506104cb57600092505050610504565b805160408051600f9290920b6020830152016040516020818303038152906040528060200190518101906104ff9190612716565b925050505b92915050565b600061051583611488565b805190915061052357600080fd5b60408082015160009081526020819052205481511461054157600080fd5b600061057c6105778460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61157f565b9050805160151461058c57600080fd5b604051732f9daeff5bd9466debfd5d3c4b1f7101524a715160611b60208201526000906105f9906034016040516020818303038152906040528051906020012084602001516105f4856000815181106105e7576105e76125c2565b602002602001015161157f565b611695565b805190915061060757600080fd5b6040805160036020820152600091610650910160405160208183030381529060405280519060200120836060015161064b866001815181106105e7576105e76125c2565b6117f7565b805190915061065e57600080fd5b610666612380565b60005b60048110156107765760208381015160408051600481850152815180820385018152908201909152805192019190912061072c9183916106a9919061272f565b6040516020016106bb91815260200190565b6040516020818303038152906040528051906020012060001c6106de919061272f565b6040516020016106f091815260200190565b60405160208183030381529060405280519060200120856060015161064b8885600261071c919061272f565b815181106105e7576105e76125c2565b82826004811061073e5761073e6125c2565b6020020152818160048110610755576107556125c2565b60200201515161076457600080fd5b8061076e81612747565b915050610669565b5060408051600660208201526001600160a01b038a16918101919091526000906107eb9060600160408051601f198184030181528282528051602091820120908301520160405160208183030381529060405280519060200120856060015161064b886006815181106105e7576105e76125c2565b80519091506107f957600080fd5b610801612380565b60005b600481101561093557602080840151604080516005938101939093526001600160a01b038e16908301526108eb9183919060600160408051601f19818403018152828252805160209182012090830152016040516020818303038152906040528051906020012060001c610878919061272f565b60405160200161088a91815260200190565b6040516020818303038152906040528051906020012060001c6108ad919061272f565b6040516020016108bf91815260200190565b60405160208183030381529060405280519060200120876060015161064b8a85600761071c919061272f565b8282600481106108fd576108fd6125c2565b6020020152818160048110610914576109146125c2565b60200201515161092357600080fd5b8061092d81612747565b915050610804565b5061093e6123b9565b60005b6002811015610a375760408051600260208201526001600160a01b038e16918101919091526109ed90829060600160408051601f19818403018152828252805160209182012090830152016040516020818303038152906040528051906020012060001c6109af919061272f565b6040516020016109c191815260200190565b60405160208183030381529060405280519060200120886060015161064b8b85600b61071c919061272f565b8282600281106109ff576109ff6125c2565b6020020152818160028110610a1657610a166125c2565b602002015151610a2557600080fd5b80610a2f81612747565b915050610941565b50610a406123e1565b600062093a808080886002602002015160200151610a5e9190612778565b610a68919061278c565b610a72919061272f565b905060005b6008811015610b4357610af96007610a928362093a8061278c565b610a9c908561272f565b6040805160ff909316602084015282015260600160408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001208a6060015161064b8d85600d61071c919061272f565b838260088110610b0b57610b0b6125c2565b6020020152828160088110610b2257610b226125c2565b602002015151610b3157600080fd5b80610b3b81612747565b915050610a77565b5060045487602001511115610c1e57602087015160045560005b6008811015610c1c57828160088110610b7857610b786125c2565b602002015160200151604051602001610b9391815260200190565b604051602081830303815290604052806020019051810190610bb59190612605565b6c03c95a2f0b4856475fe00000076000610bd28462093a8061278c565b610bdc908661272f565b8152602081019190915260400160002080546001600160801b0319166001600160801b039290921691909117905580610c1481612747565b915050610b5d565b505b604080516080810190915286516020015160a08201528060c08101604051602081830303815290604052806020019051810190610c5b9190612605565b600f0b8152602001876001602002015160200151604051602001610c8191815260200190565b604051602081830303815290604052806020019051810190610ca39190612605565b600f0b81526040888101516020908101518184015260608a015181015191909201528801516005906c01431e0fae6d7217caa00000008110610ce757610ce76125c2565b82516020808501516001600160801b03908116600160801b029216919091176003929092029290920190815560408084015160018301556060909301516002909101556001600160a01b038f1660009081526c03c95a2f0b4856475fe000000582529190912054908601511115610e1f576020858101516001600160a01b038f1660009081526c03c95a2f0b4856475fe0000005835260409081902091909155805180820190915284519091015160608201528060808101604051602081830303815290604052806020019051810190610dc19190612605565b600f0b8152602085810151810151918101919091526001600160a01b038f1660009081526c03c95a2f0b4856475fe0000008825260409020825181546001600160801b0319166001600160801b039091161781559101516001909101555b604080516080810190915284516020015160a08201528060c08101604051602081830303815290604052806020019051810190610e5c9190612605565b600f0b8152602001856001602002015160200151604051602001610e8291815260200190565b604051602081830303815290604052806020019051810190610ea49190612605565b600f0b815260408087015160209081015190830152018560036020020151602001518152506c03c95a2f0b4856475fe000000660008f6001600160a01b03166001600160a01b031681526020019081526020016000208660200151633b9aca008110610f1257610f126125c2565b6003020160008201518160000160006101000a8154816001600160801b030219169083600f0b6001600160801b0316021790555060208201518160000160106101000a8154816001600160801b030219169083600f0b6001600160801b0316021790555060408201518160010155606082015181600201559050507fdcd54ebc1dedc6b8582575473b1d51944f7bdcb15730136a908bbef1fb58181d8d8b600001518d80519060200120604051610fe7939291906001600160a01b039390931683526020830191909152604082015260600190565b60405180910390a150505050505050505050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156110c057600080336001600160a01b031663d0496d6a6040518163ffffffff1660e01b81526004016040805180830381865afa15801561106f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109391906127ab565b90925090506001600160a01b038216301480156110b05750806001145b6110b957600080fd5b50506110d7565b6002546001600160a01b031633146110d757600080fd5b6000828152602081815260409182902083905581518481529081018390527fe16e73e811796e9411f8c58ddf002de2c1e383ecaca4d22e1ddb14cdd0e514ab910160405180910390a16001548211156111305760018290555b5050565b600061113f426111dc565b905090565b6c03c95a2f0b4856475fe000000660205281600052604060002081633b9aca00811061116f57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6002546001600160a01b031633146111ae57600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600061050482426103a0565b60008060056004546c01431e0fae6d7217caa00000008110611200576112006125c2565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201839052600201546060820152915060009062093a8090611255908290612778565b61125f919061278c565b905060005b60ff81101561135f5761127a62093a808361272f565b915060008583111561128e578592506112b8565b5060008281526c03c95a2f0b4856475fe00000076020526040902054600f0b806112b8575061135f565b60408401516112c790846125ee565b6040516020016112d991815260200190565b6040516020818303038152906040528060200190518101906112fb9190612605565b846020015161130a9190612628565b845185906113199083906126c6565b600f0b9052508286141561132d575061135f565b808460200181815161133f91906127d9565b600f0b90525050604083018290528061135781612747565b915050611264565b5060008260000151600f0b121561137a575060009392505050565b815160408051600f9290920b6020830152016040516020818303038152906040528060200190518101906113ae9190612716565b949350505050565b6005816c01431e0fae6d7217caa000000081106113d257600080fd5b6003020180546001820154600290920154600f82810b9450600160801b90920490910b919084565b6000818152602081905260409020548061141357600080fd5b919050565b6003546001600160a01b0316331461142f57600080fd5b600254604080516001600160a01b0390921682523360208301527f5c486528ec3e3f0ea91181cff8116f02bfa350e03b8b6f12e00765adbb5af85c910160405180910390a1600280546001600160a01b03191633179055565b60408051608080820183526000808352602080840182905283850182905260608085018390528551938401865282845283820183905283860183905283018290528451808601865282815281018290528451808601909552855185528581019085015291929091906114f99061157f565b9050600b81511161150957600080fd5b61152c8160038151811061151f5761151f6125c2565b6020026020010151611885565b6020830152805161154a908290600890811061151f5761151f6125c2565b60408301528051611568908290600b90811061151f5761151f6125c2565b606083015250825160209093019290922082525090565b606061158a826118d2565b61159357600080fd5b600061159e8361190b565b905060008167ffffffffffffffff8111156115bb576115bb61246e565b60405190808252806020026020018201604052801561160057816020015b60408051808201909152600080825260208201528152602001906001900390816115d95790505b5090506000611612856020015161198e565b8560200151611621919061272f565b90506000805b8481101561168a5761163883611a09565b9150604051806040016040528083815260200184815250848281518110611661576116616125c2565b6020908102919091010152611676828461272f565b92508061168281612747565b915050611627565b509195945050505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915260006116ee84866040516020016116d991815260200190565b60405160208183030381529060405285611ab2565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152909150815161172b5791506117f09050565b60006117616105778460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b9050805160041461177157600080fd5b60018252805161178c90829060009061151f5761151f6125c2565b602083015280516117aa908290600190811061151f5761151f6125c2565b604083015280516117c8908290600290811061151f5761151f6125c2565b606083015280516117e6908290600390811061151f5761151f6125c2565b6080830152509150505b9392505050565b6040805180820190915260008082526020820152600061182484866040516020016116d991815260200190565b604080518082019091526000808252602082015290915081511561187c576001815260408051808201825260008082526020918201528151808301909252835182528084019082015261187690611885565b60208201525b95945050505050565b80516000901580159061189a57508151602110155b6118a357600080fd5b6000806118af84611ee1565b8151919350915060208210156113ae5760208290036101000a9004949350505050565b80516000906118e357506000919050565b6020820151805160001a9060c0821015611901575060009392505050565b5060019392505050565b805160009061191c57506000919050565b60008061192c846020015161198e565b846020015161193b919061272f565b9050600084600001518560200151611953919061272f565b90505b808210156119855761196782611a09565b611971908361272f565b91508261197d81612747565b935050611956565b50909392505050565b8051600090811a60808110156119a75750600092915050565b60b88110806119c2575060c081108015906119c2575060f881105b156119d05750600192915050565b60c08110156119fd576119e5600160b8612828565b6119f29060ff16826125ee565b6117f090600161272f565b6119e5600160f8612828565b80516000908190811a6080811015611a245760019150611aab565b60b8811015611a4a57611a386080826125ee565b611a4390600161272f565b9150611aab565b60c0811015611a775760b78103600185019450806020036101000a85510460018201810193505050611aab565b60f8811015611a8b57611a3860c0826125ee565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60606000611ac1846000611f28565b90506000806060611ae5604051806040016040528060008152602001600081525090565b8651611b33577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218914611b1757600080fd5b505060408051600081526020810190915293506117f092505050565b60005b8751811015611ed45780158015611b755750611b71888281518110611b5d57611b5d6125c2565b602002602001015160208101519051902090565b8a14155b15611b7f57600080fd5b8015801590611baf5750611bab888281518110611b9e57611b9e6125c2565b60200260200101516120cb565b8414155b15611bb957600080fd5b611bce8882815181106105e7576105e76125c2565b9250825160021415611d7c5760006060611c09611c0486600081518110611bf757611bf76125c2565b6020026020010151612120565b61219e565b90925090506000611c1b888a8461223a565b9050611c27818961272f565b97508151811015611c8a5760018b51611c4091906125ee565b841015611c4c57600080fd5b60005b6040519080825280601f01601f191660200182016040528015611c79576020820181803683370190505b5099505050505050505050506117f0565b8215611cf05760018b51611c9e91906125ee565b841015611caa57600080fd5b8851881015611cba576000611c4f565b85600181518110611ccd57611ccd6125c2565b60200260200101519450611ce085612120565b99505050505050505050506117f0565b60018b51611cfe91906125ee565b841415611d0a57600080fd5b611d2d86600181518110611d2057611d206125c2565b60200260200101516118d2565b611d5b57611d5486600181518110611d4757611d476125c2565b60200260200101516122c5565b9650611d74565b611d7186600181518110611b5d57611b5d6125c2565b96505b505050611ec2565b825160111415611ec25785518514611e86576000868681518110611da257611da26125c2565b016020015160f81c9050611db760018761272f565b955060108160ff1610611dc957600080fd5b611dee848260ff1681518110611de157611de16125c2565b60200260200101516122dd565b15611e2a5760018951611e0191906125ee565b8214611e0c57600080fd5b505060408051600081526020810190915295506117f0945050505050565b611e42848260ff1681518110611d2057611d206125c2565b611e6557611e5e848260ff1681518110611d4757611d476125c2565b9450611e80565b611e7d848260ff1681518110611b5d57611b5d6125c2565b94505b50611ec2565b60018851611e9491906125ee565b8114611e9f57600080fd5b611eb583601081518110611bf757611bf76125c2565b96505050505050506117f0565b80611ecc81612747565b915050611b36565b5050505050509392505050565b6000806000611ef3846020015161198e565b90506000818560200151611f07919061272f565b90506000828660000151611f1b91906125ee565b9196919550909350505050565b60606000835111611f3857600080fd5b600083516002611f48919061278c565b905080831115611f5757600080fd5b611f6183826125ee565b90508067ffffffffffffffff811115611f7c57611f7c61246e565b6040519080825280601f01601f191660200182016040528015611fa6576020820181803683370190505b5091506000835b611fb7838661272f565b8110156120b257611fc960028261284b565b61203257600486611fdb600284612778565b81518110611feb57611feb6125c2565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b848381518110612016576120166125c2565b60200101906001600160f81b031916908160001a905350612093565b600086612040600284612778565b81518110612050576120506125c2565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061207b5761207b6125c2565b60200101906001600160f81b031916908160001a9053505b61209e60018361272f565b91506120ab60018261272f565b9050611fad565b50825181146120c3576120c361285f565b505092915050565b60006020826000015110156120e857602082015182519020610504565b60208201518251902060405160200161210391815260200190565b604051602081830303815290604052805190602001209050919050565b805160609061212e57600080fd5b60008061213a84611ee1565b9150915060008167ffffffffffffffff8111156121595761215961246e565b6040519080825280601f01601f191660200182016040528015612183576020820181803683370190505b50905060208101612195848285612300565b50949350505050565b6000606060008351116121b057600080fd5b60006004846000815181106121c7576121c76125c2565b60209101015160f81c901c600f1690506000816121ea5750600092506002612224565b81600114156121ff5750600092506001612224565b81600214156122145750600192506002612224565b816003141561012b575060019250825b8361222f8683611f28565b935093505050915091565b6000805b835161224a868361272f565b1080156122575750825181105b156113ae5782818151811061226e5761226e6125c2565b01602001516001600160f81b03191684612288878461272f565b81518110612298576122986125c2565b01602001516001600160f81b031916146122b35790506117f0565b806122bd81612747565b91505061223e565b60008060006122d384611ee1565b9020949350505050565b80516000906001146122f157506000919050565b50602001515160001a60801490565b8061230a57505050565b60208110612342578251825261232160208461272f565b925061232e60208361272f565b915061233b6020826125ee565b905061230a565b801561237b57600060016123578360206125ee565b61236390610100612959565b61236d91906125ee565b845184518216911916178352505b505050565b60405180608001604052806004905b604080518082019091526000808252602082015281526020019060019003908161238f5790505090565b604080516080810182526000918101828152606082019290925290815260016020820161238f565b60408051610140810190915260006101008201818152610120830191909152815260076020820161238f565b6001600160a01b038116811461242257600080fd5b50565b6000806040838503121561243857600080fd5b82356124438161240d565b946020939093013593505050565b60006020828403121561246357600080fd5b81356117f08161240d565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261249557600080fd5b813567ffffffffffffffff808211156124b0576124b061246e565b604051601f8301601f19908116603f011681019082821181831017156124d8576124d861246e565b816040528381528660208588010111156124f157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561252657600080fd5b83356125318161240d565b9250602084013567ffffffffffffffff8082111561254e57600080fd5b61255a87838801612484565b9350604086013591508082111561257057600080fd5b5061257d86828701612484565b9150509250925092565b6000806040838503121561259a57600080fd5b50508035926020909101359150565b6000602082840312156125bb57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015612600576126006125d8565b500390565b60006020828403121561261757600080fd5b815180600f0b81146117f057600080fd5b600081600f0b83600f0b60016001607f1b03600082136000841383830485118282161615612658576126586125d8565b6f7fffffffffffffffffffffffffffffff196000851282811687830587121615612684576126846125d8565b600087129250858205871284841616156126a0576126a06125d8565b858505871281841616156126b6576126b66125d8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156126f1576126f16125d8565b8160016001607f1b0301831381161561270c5761270c6125d8565b5090039392505050565b60006020828403121561272857600080fd5b5051919050565b60008219821115612742576127426125d8565b500190565b600060001982141561275b5761275b6125d8565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261278757612787612762565b500490565b60008160001904831182151516156127a6576127a66125d8565b500290565b600080604083850312156127be57600080fd5b82516127c98161240d565b6020939093015192949293505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615612803576128036125d8565b8260016001607f1b031903821281161561281f5761281f6125d8565b50019392505050565b600060ff821660ff841680821015612842576128426125d8565b90039392505050565b60008261285a5761285a612762565b500690565b634e487b7160e01b600052600160045260246000fd5b600181815b808511156128b0578160001904821115612896576128966125d8565b808516156128a357918102915b93841c939080029061287a565b509250929050565b6000826128c757506001610504565b816128d457506000610504565b81600181146128ea57600281146128f457612910565b6001915050610504565b60ff841115612905576129056125d8565b50506001821b610504565b5060208310610133831016604e8410600b8410161715612933575081810a610504565b61293d8383612875565b8060001904821115612951576129516125d8565b029392505050565b60006117f083836128b856fea264697066735822122079d58c8c7c796226c6ba39c4186821025994a29b539d14eb489725f608714b3d64736f6c634300080c003300000000000000000000000037414a8662bc1d25be3ee51fb27c2686e2490a89
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061012b5760003560e01c806370a08231116100ad578063bd85b03911610071578063bd85b0391461030b578063cbf9fe5f1461031e578063d1febfb914610372578063e4160ddb14610385578063e5ea47b81461039857600080fd5b806370a082311461029157806371197484146102a45780638da5cb5b146102e6578063900cf0cf146102f9578063aa34453f1461030257600080fd5b80631ec0cdc1116100f45780631ec0cdc1146101b25780632090356b146101dd57806328d09d47146102045780633fb9fbd51461023f5780636b441a401461027e57600080fd5b8062fdd58e14610130578063010ae75714610156578063068b4668146101825780630fb997cc1461019757806318160ddd146101aa575b600080fd5b61014361013e366004612425565b6103a0565b6040519081526020015b60405180910390f35b610143610164366004612451565b6c03c95a2f0b4856475fe00000056020526000908152604090205481565b610195610190366004612511565b61050a565b005b6101956101a5366004612587565b610ffe565b610143611134565b6003546101c5906001600160a01b031681565b6040516001600160a01b03909116815260200161014d565b6101c57f00000000000000000000000037414a8662bc1d25be3ee51fb27c2686e2490a8981565b610217610212366004612425565b611144565b60408051600f95860b81529390940b602084015292820152606081019190915260800161014d565b61026e61024d3660046125a9565b6c03c95a2f0b4856475fe00000096020526000908152604090205460ff1681565b604051901515815260200161014d565b61019561028c366004612451565b611197565b61014361029f366004612451565b6111d0565b6102d36102b23660046125a9565b6c03c95a2f0b4856475fe000000760205260009081526040902054600f0b81565b604051600f9190910b815260200161014d565b6002546101c5906001600160a01b031681565b61014360045481565b61014360015481565b6101436103193660046125a9565b6111dc565b61035861032c366004612451565b6c03c95a2f0b4856475fe00000086020526000908152604090208054600190910154600f9190910b9082565b60408051600f9390930b835260208301919091520161014d565b6102176103803660046125a9565b6113b6565b6101436103933660046125a9565b6113fa565b610195611418565b6001600160a01b03821660009081526c03c95a2f0b4856475fe00000056020526040812054806103d4576000915050610504565b6001600160a01b03841660009081526c03c95a2f0b4856475fe00000066020526040812082633b9aca00811061040c5761040c6125c2565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201839052600201546060820152915061045890856125ee565b60405160200161046a91815260200190565b60405160208183030381529060405280602001905181019061048c9190612605565b816020015161049b9190612628565b815182906104aa9083906126c6565b600f90810b90915282516000910b121590506104cb57600092505050610504565b805160408051600f9290920b6020830152016040516020818303038152906040528060200190518101906104ff9190612716565b925050505b92915050565b600061051583611488565b805190915061052357600080fd5b60408082015160009081526020819052205481511461054157600080fd5b600061057c6105778460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b61157f565b9050805160151461058c57600080fd5b604051732f9daeff5bd9466debfd5d3c4b1f7101524a715160611b60208201526000906105f9906034016040516020818303038152906040528051906020012084602001516105f4856000815181106105e7576105e76125c2565b602002602001015161157f565b611695565b805190915061060757600080fd5b6040805160036020820152600091610650910160405160208183030381529060405280519060200120836060015161064b866001815181106105e7576105e76125c2565b6117f7565b805190915061065e57600080fd5b610666612380565b60005b60048110156107765760208381015160408051600481850152815180820385018152908201909152805192019190912061072c9183916106a9919061272f565b6040516020016106bb91815260200190565b6040516020818303038152906040528051906020012060001c6106de919061272f565b6040516020016106f091815260200190565b60405160208183030381529060405280519060200120856060015161064b8885600261071c919061272f565b815181106105e7576105e76125c2565b82826004811061073e5761073e6125c2565b6020020152818160048110610755576107556125c2565b60200201515161076457600080fd5b8061076e81612747565b915050610669565b5060408051600660208201526001600160a01b038a16918101919091526000906107eb9060600160408051601f198184030181528282528051602091820120908301520160405160208183030381529060405280519060200120856060015161064b886006815181106105e7576105e76125c2565b80519091506107f957600080fd5b610801612380565b60005b600481101561093557602080840151604080516005938101939093526001600160a01b038e16908301526108eb9183919060600160408051601f19818403018152828252805160209182012090830152016040516020818303038152906040528051906020012060001c610878919061272f565b60405160200161088a91815260200190565b6040516020818303038152906040528051906020012060001c6108ad919061272f565b6040516020016108bf91815260200190565b60405160208183030381529060405280519060200120876060015161064b8a85600761071c919061272f565b8282600481106108fd576108fd6125c2565b6020020152818160048110610914576109146125c2565b60200201515161092357600080fd5b8061092d81612747565b915050610804565b5061093e6123b9565b60005b6002811015610a375760408051600260208201526001600160a01b038e16918101919091526109ed90829060600160408051601f19818403018152828252805160209182012090830152016040516020818303038152906040528051906020012060001c6109af919061272f565b6040516020016109c191815260200190565b60405160208183030381529060405280519060200120886060015161064b8b85600b61071c919061272f565b8282600281106109ff576109ff6125c2565b6020020152818160028110610a1657610a166125c2565b602002015151610a2557600080fd5b80610a2f81612747565b915050610941565b50610a406123e1565b600062093a808080886002602002015160200151610a5e9190612778565b610a68919061278c565b610a72919061272f565b905060005b6008811015610b4357610af96007610a928362093a8061278c565b610a9c908561272f565b6040805160ff909316602084015282015260600160408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001208a6060015161064b8d85600d61071c919061272f565b838260088110610b0b57610b0b6125c2565b6020020152828160088110610b2257610b226125c2565b602002015151610b3157600080fd5b80610b3b81612747565b915050610a77565b5060045487602001511115610c1e57602087015160045560005b6008811015610c1c57828160088110610b7857610b786125c2565b602002015160200151604051602001610b9391815260200190565b604051602081830303815290604052806020019051810190610bb59190612605565b6c03c95a2f0b4856475fe00000076000610bd28462093a8061278c565b610bdc908661272f565b8152602081019190915260400160002080546001600160801b0319166001600160801b039290921691909117905580610c1481612747565b915050610b5d565b505b604080516080810190915286516020015160a08201528060c08101604051602081830303815290604052806020019051810190610c5b9190612605565b600f0b8152602001876001602002015160200151604051602001610c8191815260200190565b604051602081830303815290604052806020019051810190610ca39190612605565b600f0b81526040888101516020908101518184015260608a015181015191909201528801516005906c01431e0fae6d7217caa00000008110610ce757610ce76125c2565b82516020808501516001600160801b03908116600160801b029216919091176003929092029290920190815560408084015160018301556060909301516002909101556001600160a01b038f1660009081526c03c95a2f0b4856475fe000000582529190912054908601511115610e1f576020858101516001600160a01b038f1660009081526c03c95a2f0b4856475fe0000005835260409081902091909155805180820190915284519091015160608201528060808101604051602081830303815290604052806020019051810190610dc19190612605565b600f0b8152602085810151810151918101919091526001600160a01b038f1660009081526c03c95a2f0b4856475fe0000008825260409020825181546001600160801b0319166001600160801b039091161781559101516001909101555b604080516080810190915284516020015160a08201528060c08101604051602081830303815290604052806020019051810190610e5c9190612605565b600f0b8152602001856001602002015160200151604051602001610e8291815260200190565b604051602081830303815290604052806020019051810190610ea49190612605565b600f0b815260408087015160209081015190830152018560036020020151602001518152506c03c95a2f0b4856475fe000000660008f6001600160a01b03166001600160a01b031681526020019081526020016000208660200151633b9aca008110610f1257610f126125c2565b6003020160008201518160000160006101000a8154816001600160801b030219169083600f0b6001600160801b0316021790555060208201518160000160106101000a8154816001600160801b030219169083600f0b6001600160801b0316021790555060408201518160010155606082015181600201559050507fdcd54ebc1dedc6b8582575473b1d51944f7bdcb15730136a908bbef1fb58181d8d8b600001518d80519060200120604051610fe7939291906001600160a01b039390931683526020830191909152604082015260600190565b60405180910390a150505050505050505050505050565b336001600160a01b037f00000000000000000000000037414a8662bc1d25be3ee51fb27c2686e2490a891614156110c057600080336001600160a01b031663d0496d6a6040518163ffffffff1660e01b81526004016040805180830381865afa15801561106f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109391906127ab565b90925090506001600160a01b038216301480156110b05750806001145b6110b957600080fd5b50506110d7565b6002546001600160a01b031633146110d757600080fd5b6000828152602081815260409182902083905581518481529081018390527fe16e73e811796e9411f8c58ddf002de2c1e383ecaca4d22e1ddb14cdd0e514ab910160405180910390a16001548211156111305760018290555b5050565b600061113f426111dc565b905090565b6c03c95a2f0b4856475fe000000660205281600052604060002081633b9aca00811061116f57600080fd5b6003020180546001820154600290920154600f82810b9550600160801b90920490910b925084565b6002546001600160a01b031633146111ae57600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600061050482426103a0565b60008060056004546c01431e0fae6d7217caa00000008110611200576112006125c2565b60408051608081018252600392909202929092018054600f81810b8452600160801b909104900b60208301526001810154928201839052600201546060820152915060009062093a8090611255908290612778565b61125f919061278c565b905060005b60ff81101561135f5761127a62093a808361272f565b915060008583111561128e578592506112b8565b5060008281526c03c95a2f0b4856475fe00000076020526040902054600f0b806112b8575061135f565b60408401516112c790846125ee565b6040516020016112d991815260200190565b6040516020818303038152906040528060200190518101906112fb9190612605565b846020015161130a9190612628565b845185906113199083906126c6565b600f0b9052508286141561132d575061135f565b808460200181815161133f91906127d9565b600f0b90525050604083018290528061135781612747565b915050611264565b5060008260000151600f0b121561137a575060009392505050565b815160408051600f9290920b6020830152016040516020818303038152906040528060200190518101906113ae9190612716565b949350505050565b6005816c01431e0fae6d7217caa000000081106113d257600080fd5b6003020180546001820154600290920154600f82810b9450600160801b90920490910b919084565b6000818152602081905260409020548061141357600080fd5b919050565b6003546001600160a01b0316331461142f57600080fd5b600254604080516001600160a01b0390921682523360208301527f5c486528ec3e3f0ea91181cff8116f02bfa350e03b8b6f12e00765adbb5af85c910160405180910390a1600280546001600160a01b03191633179055565b60408051608080820183526000808352602080840182905283850182905260608085018390528551938401865282845283820183905283860183905283018290528451808601865282815281018290528451808601909552855185528581019085015291929091906114f99061157f565b9050600b81511161150957600080fd5b61152c8160038151811061151f5761151f6125c2565b6020026020010151611885565b6020830152805161154a908290600890811061151f5761151f6125c2565b60408301528051611568908290600b90811061151f5761151f6125c2565b606083015250825160209093019290922082525090565b606061158a826118d2565b61159357600080fd5b600061159e8361190b565b905060008167ffffffffffffffff8111156115bb576115bb61246e565b60405190808252806020026020018201604052801561160057816020015b60408051808201909152600080825260208201528152602001906001900390816115d95790505b5090506000611612856020015161198e565b8560200151611621919061272f565b90506000805b8481101561168a5761163883611a09565b9150604051806040016040528083815260200184815250848281518110611661576116616125c2565b6020908102919091010152611676828461272f565b92508061168281612747565b915050611627565b509195945050505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915260006116ee84866040516020016116d991815260200190565b60405160208183030381529060405285611ab2565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152909150815161172b5791506117f09050565b60006117616105778460408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b9050805160041461177157600080fd5b60018252805161178c90829060009061151f5761151f6125c2565b602083015280516117aa908290600190811061151f5761151f6125c2565b604083015280516117c8908290600290811061151f5761151f6125c2565b606083015280516117e6908290600390811061151f5761151f6125c2565b6080830152509150505b9392505050565b6040805180820190915260008082526020820152600061182484866040516020016116d991815260200190565b604080518082019091526000808252602082015290915081511561187c576001815260408051808201825260008082526020918201528151808301909252835182528084019082015261187690611885565b60208201525b95945050505050565b80516000901580159061189a57508151602110155b6118a357600080fd5b6000806118af84611ee1565b8151919350915060208210156113ae5760208290036101000a9004949350505050565b80516000906118e357506000919050565b6020820151805160001a9060c0821015611901575060009392505050565b5060019392505050565b805160009061191c57506000919050565b60008061192c846020015161198e565b846020015161193b919061272f565b9050600084600001518560200151611953919061272f565b90505b808210156119855761196782611a09565b611971908361272f565b91508261197d81612747565b935050611956565b50909392505050565b8051600090811a60808110156119a75750600092915050565b60b88110806119c2575060c081108015906119c2575060f881105b156119d05750600192915050565b60c08110156119fd576119e5600160b8612828565b6119f29060ff16826125ee565b6117f090600161272f565b6119e5600160f8612828565b80516000908190811a6080811015611a245760019150611aab565b60b8811015611a4a57611a386080826125ee565b611a4390600161272f565b9150611aab565b60c0811015611a775760b78103600185019450806020036101000a85510460018201810193505050611aab565b60f8811015611a8b57611a3860c0826125ee565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b60606000611ac1846000611f28565b90506000806060611ae5604051806040016040528060008152602001600081525090565b8651611b33577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218914611b1757600080fd5b505060408051600081526020810190915293506117f092505050565b60005b8751811015611ed45780158015611b755750611b71888281518110611b5d57611b5d6125c2565b602002602001015160208101519051902090565b8a14155b15611b7f57600080fd5b8015801590611baf5750611bab888281518110611b9e57611b9e6125c2565b60200260200101516120cb565b8414155b15611bb957600080fd5b611bce8882815181106105e7576105e76125c2565b9250825160021415611d7c5760006060611c09611c0486600081518110611bf757611bf76125c2565b6020026020010151612120565b61219e565b90925090506000611c1b888a8461223a565b9050611c27818961272f565b97508151811015611c8a5760018b51611c4091906125ee565b841015611c4c57600080fd5b60005b6040519080825280601f01601f191660200182016040528015611c79576020820181803683370190505b5099505050505050505050506117f0565b8215611cf05760018b51611c9e91906125ee565b841015611caa57600080fd5b8851881015611cba576000611c4f565b85600181518110611ccd57611ccd6125c2565b60200260200101519450611ce085612120565b99505050505050505050506117f0565b60018b51611cfe91906125ee565b841415611d0a57600080fd5b611d2d86600181518110611d2057611d206125c2565b60200260200101516118d2565b611d5b57611d5486600181518110611d4757611d476125c2565b60200260200101516122c5565b9650611d74565b611d7186600181518110611b5d57611b5d6125c2565b96505b505050611ec2565b825160111415611ec25785518514611e86576000868681518110611da257611da26125c2565b016020015160f81c9050611db760018761272f565b955060108160ff1610611dc957600080fd5b611dee848260ff1681518110611de157611de16125c2565b60200260200101516122dd565b15611e2a5760018951611e0191906125ee565b8214611e0c57600080fd5b505060408051600081526020810190915295506117f0945050505050565b611e42848260ff1681518110611d2057611d206125c2565b611e6557611e5e848260ff1681518110611d4757611d476125c2565b9450611e80565b611e7d848260ff1681518110611b5d57611b5d6125c2565b94505b50611ec2565b60018851611e9491906125ee565b8114611e9f57600080fd5b611eb583601081518110611bf757611bf76125c2565b96505050505050506117f0565b80611ecc81612747565b915050611b36565b5050505050509392505050565b6000806000611ef3846020015161198e565b90506000818560200151611f07919061272f565b90506000828660000151611f1b91906125ee565b9196919550909350505050565b60606000835111611f3857600080fd5b600083516002611f48919061278c565b905080831115611f5757600080fd5b611f6183826125ee565b90508067ffffffffffffffff811115611f7c57611f7c61246e565b6040519080825280601f01601f191660200182016040528015611fa6576020820181803683370190505b5091506000835b611fb7838661272f565b8110156120b257611fc960028261284b565b61203257600486611fdb600284612778565b81518110611feb57611feb6125c2565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b848381518110612016576120166125c2565b60200101906001600160f81b031916908160001a905350612093565b600086612040600284612778565b81518110612050576120506125c2565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061207b5761207b6125c2565b60200101906001600160f81b031916908160001a9053505b61209e60018361272f565b91506120ab60018261272f565b9050611fad565b50825181146120c3576120c361285f565b505092915050565b60006020826000015110156120e857602082015182519020610504565b60208201518251902060405160200161210391815260200190565b604051602081830303815290604052805190602001209050919050565b805160609061212e57600080fd5b60008061213a84611ee1565b9150915060008167ffffffffffffffff8111156121595761215961246e565b6040519080825280601f01601f191660200182016040528015612183576020820181803683370190505b50905060208101612195848285612300565b50949350505050565b6000606060008351116121b057600080fd5b60006004846000815181106121c7576121c76125c2565b60209101015160f81c901c600f1690506000816121ea5750600092506002612224565b81600114156121ff5750600092506001612224565b81600214156122145750600192506002612224565b816003141561012b575060019250825b8361222f8683611f28565b935093505050915091565b6000805b835161224a868361272f565b1080156122575750825181105b156113ae5782818151811061226e5761226e6125c2565b01602001516001600160f81b03191684612288878461272f565b81518110612298576122986125c2565b01602001516001600160f81b031916146122b35790506117f0565b806122bd81612747565b91505061223e565b60008060006122d384611ee1565b9020949350505050565b80516000906001146122f157506000919050565b50602001515160001a60801490565b8061230a57505050565b60208110612342578251825261232160208461272f565b925061232e60208361272f565b915061233b6020826125ee565b905061230a565b801561237b57600060016123578360206125ee565b61236390610100612959565b61236d91906125ee565b845184518216911916178352505b505050565b60405180608001604052806004905b604080518082019091526000808252602082015281526020019060019003908161238f5790505090565b604080516080810182526000918101828152606082019290925290815260016020820161238f565b60408051610140810190915260006101008201818152610120830191909152815260076020820161238f565b6001600160a01b038116811461242257600080fd5b50565b6000806040838503121561243857600080fd5b82356124438161240d565b946020939093013593505050565b60006020828403121561246357600080fd5b81356117f08161240d565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261249557600080fd5b813567ffffffffffffffff808211156124b0576124b061246e565b604051601f8301601f19908116603f011681019082821181831017156124d8576124d861246e565b816040528381528660208588010111156124f157600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060006060848603121561252657600080fd5b83356125318161240d565b9250602084013567ffffffffffffffff8082111561254e57600080fd5b61255a87838801612484565b9350604086013591508082111561257057600080fd5b5061257d86828701612484565b9150509250925092565b6000806040838503121561259a57600080fd5b50508035926020909101359150565b6000602082840312156125bb57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015612600576126006125d8565b500390565b60006020828403121561261757600080fd5b815180600f0b81146117f057600080fd5b600081600f0b83600f0b60016001607f1b03600082136000841383830485118282161615612658576126586125d8565b6f7fffffffffffffffffffffffffffffff196000851282811687830587121615612684576126846125d8565b600087129250858205871284841616156126a0576126a06125d8565b858505871281841616156126b6576126b66125d8565b5050509290910295945050505050565b600081600f0b83600f0b600081128160016001607f1b0319018312811516156126f1576126f16125d8565b8160016001607f1b0301831381161561270c5761270c6125d8565b5090039392505050565b60006020828403121561272857600080fd5b5051919050565b60008219821115612742576127426125d8565b500190565b600060001982141561275b5761275b6125d8565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261278757612787612762565b500490565b60008160001904831182151516156127a6576127a66125d8565b500290565b600080604083850312156127be57600080fd5b82516127c98161240d565b6020939093015192949293505050565b600081600f0b83600f0b600082128260016001607f1b0303821381151615612803576128036125d8565b8260016001607f1b031903821281161561281f5761281f6125d8565b50019392505050565b600060ff821660ff841680821015612842576128426125d8565b90039392505050565b60008261285a5761285a612762565b500690565b634e487b7160e01b600052600160045260246000fd5b600181815b808511156128b0578160001904821115612896576128966125d8565b808516156128a357918102915b93841c939080029061287a565b509250929050565b6000826128c757506001610504565b816128d457506000610504565b81600181146128ea57600281146128f457612910565b6001915050610504565b60ff841115612905576129056125d8565b50506001821b610504565b5060208310610133831016604e8410600b8410161715612933575081810a610504565b61293d8383612875565b8060001904821115612951576129516125d8565b029392505050565b60006117f083836128b856fea264697066735822122079d58c8c7c796226c6ba39c4186821025994a29b539d14eb489725f608714b3d64736f6c634300080c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000037414a8662bc1d25be3ee51fb27c2686e2490a89
-----Decoded View---------------
Arg [0] : _anycall (address): 0x37414a8662bC1D25be3ee51Fb27C2686e2490A89
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000037414a8662bc1d25be3ee51fb27c2686e2490a89
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.