ETH Price: $3,370.72 (+0.01%)

Contract

0x12F407340697Ae0b177546E535b91A5be021fBF9

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Submit_state1067767882023-07-12 8:59:13555 days ago1689152353IN
0x12F40734...be021fBF9
0 ETH0.0097050514510.1
Commit_transfer_...44634552022-03-15 9:51:581039 days ago1647337918IN
0x12F40734...be021fBF9
0 ETH0.0000734891750.001

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
1075566192023-07-30 10:13:35537 days ago1690712015
0x12F40734...be021fBF9
0 ETH
1075566192023-07-30 10:13:35537 days ago1690712015
0x12F40734...be021fBF9
0 ETH
1075553102023-07-30 9:29:57537 days ago1690709397
0x12F40734...be021fBF9
0 ETH
1075553102023-07-30 9:29:57537 days ago1690709397
0x12F40734...be021fBF9
0 ETH
1075542342023-07-30 8:54:05537 days ago1690707245
0x12F40734...be021fBF9
0 ETH
1075542342023-07-30 8:54:05537 days ago1690707245
0x12F40734...be021fBF9
0 ETH
1075528092023-07-30 8:06:35537 days ago1690704395
0x12F40734...be021fBF9
0 ETH
1075528092023-07-30 8:06:35537 days ago1690704395
0x12F40734...be021fBF9
0 ETH
1075524462023-07-30 7:54:29537 days ago1690703669
0x12F40734...be021fBF9
0 ETH
1075524462023-07-30 7:54:29537 days ago1690703669
0x12F40734...be021fBF9
0 ETH
1075521782023-07-30 7:45:33537 days ago1690703133
0x12F40734...be021fBF9
0 ETH
1075521782023-07-30 7:45:33537 days ago1690703133
0x12F40734...be021fBF9
0 ETH
1075519182023-07-30 7:36:53537 days ago1690702613
0x12F40734...be021fBF9
0 ETH
1075519182023-07-30 7:36:53537 days ago1690702613
0x12F40734...be021fBF9
0 ETH
1075508052023-07-30 6:59:47537 days ago1690700387
0x12F40734...be021fBF9
0 ETH
1075508052023-07-30 6:59:47537 days ago1690700387
0x12F40734...be021fBF9
0 ETH
1075506062023-07-30 6:53:09537 days ago1690699989
0x12F40734...be021fBF9
0 ETH
1075506062023-07-30 6:53:09537 days ago1690699989
0x12F40734...be021fBF9
0 ETH
1075506062023-07-30 6:53:09537 days ago1690699989
0x12F40734...be021fBF9
0 ETH
1075506062023-07-30 6:53:09537 days ago1690699989
0x12F40734...be021fBF9
0 ETH
1075488532023-07-30 5:54:43537 days ago1690696483
0x12F40734...be021fBF9
0 ETH
1075488532023-07-30 5:54:43537 days ago1690696483
0x12F40734...be021fBF9
0 ETH
1075488532023-07-30 5:54:43537 days ago1690696483
0x12F40734...be021fBF9
0 ETH
1075488532023-07-30 5:54:43537 days ago1690696483
0x12F40734...be021fBF9
0 ETH
1075417692023-07-30 1:58:35538 days ago1690682315
0x12F40734...be021fBF9
0 ETH
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
VotingEscrowStateOracle

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
File 1 of 4 : VotingEscrowStateOracle.sol
// 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;
    }
}

File 2 of 4 : RLPReader.sol
// 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))
            }
        }
    }
}

File 3 of 4 : StateProofVerifier.sol
// 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;
    }

}

File 4 of 4 : MerklePatriciaProofVerifier.sol
// 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;
    }
}

Settings
{
  "evmVersion": "istanbul",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "libraries": {
    "VotingEscrowStateOracle.sol": {}
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"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"}]

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


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.