S Price: $0.067973 (-2.45%)
Gas: 55 Gwei

Contract

0x38334e319D257d8f580f66393d25A6CD647A6AbC

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Verify Balance B...581841132025-12-17 17:53:4239 days ago1765994022IN
Curve: Verifier
0 S0.3106884555
Verify Balance B...581527212025-12-17 11:22:5939 days ago1765970579IN
Curve: Verifier
0 S0.3122177355
Verify Balance B...580938862025-12-16 18:21:5640 days ago1765909316IN
Curve: Verifier
0 S0.3090618355
Verify Balance B...580922142025-12-16 17:52:4140 days ago1765907561IN
Curve: Verifier
0 S0.1297830655
Verify Balance B...580921772025-12-16 17:52:1740 days ago1765907537IN
Curve: Verifier
0 S0.3094978155
Verify Balance B...580921552025-12-16 17:51:5440 days ago1765907514IN
Curve: Verifier
0 S0.3134760255
Verify Balance B...500071822025-10-10 13:30:41107 days ago1760103041IN
Curve: Verifier
0 S0.3152476255
Verify Balance B...497121752025-10-08 0:37:23110 days ago1759883843IN
Curve: Verifier
0 S0.3159834755
Verify Balance B...495537132025-10-06 18:48:01111 days ago1759776481IN
Curve: Verifier
0 S0.3185067655
Verify Balance B...482508972025-09-26 3:38:17122 days ago1758857897IN
Curve: Verifier
0 S0.3144659655
Verify Total By ...482500972025-09-26 3:29:30122 days ago1758857370IN
Curve: Verifier
0 S0.1859149655
Verify Balance B...479685112025-09-24 1:07:12124 days ago1758676032IN
Curve: Verifier
0 S0.3148488755
Verify Balance B...463204732025-09-10 0:24:44138 days ago1757463884IN
Curve: Verifier
0 S0.3158344755
Verify Balance B...462060482025-09-09 0:24:46139 days ago1757377486IN
Curve: Verifier
0 S0.3124564355
Verify Total By ...462051822025-09-09 0:15:15139 days ago1757376915IN
Curve: Verifier
0 S0.1826641855
Verify Balance B...447633712025-08-27 17:55:16151 days ago1756317316IN
Curve: Verifier
0 S0.3140234955
Verify Balance B...446990302025-08-27 6:34:46152 days ago1756276486IN
Curve: Verifier
0 S0.3158031255
Verify Balance B...436753432025-08-19 14:04:48159 days ago1755612288IN
Curve: Verifier
0 S0.3090553455
Verify Balance B...429631022025-08-14 10:25:02164 days ago1755167102IN
Curve: Verifier
0 S0.3141308555
Verify Balance B...427487952025-08-13 4:23:46166 days ago1755059026IN
Curve: Verifier
0 S0.3147747355
Verify Balance B...420881882025-08-08 2:49:56171 days ago1754621396IN
Curve: Verifier
0 S0.3107281155
Verify Total By ...420872832025-08-08 2:40:00171 days ago1754620800IN
Curve: Verifier
0 S0.1769268655
Verify Total By ...420866762025-08-08 2:31:30171 days ago1754620290IN
Curve: Verifier
0 S0.182348755
Verify Balance B...408281452025-07-30 3:31:10180 days ago1753846270IN
Curve: Verifier
0 S0.312705855
Verify Balance B...400589622025-07-24 18:26:45185 days ago1753381605IN
Curve: Verifier
0 S0.3071570755
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Cross-Chain Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x4D1AF991...26Bc9bb61 in Fraxtal Mainnet
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
VecrvVerifier

Compiler Version
v0.8.18+commit.87f61d96

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

import "contracts/verifiers/VecrvVerifierCore.sol";
import {RLPReader} from "contracts/RLPReader.sol";
import {StateProofVerifier as Verifier} from "contracts/libs/StateProofVerifier.sol";

interface IBlockHashOracle {
    function get_block_hash(uint256 _number) external view returns (bytes32);
    function get_state_root(uint256 _number) external view returns (bytes32);
}

contract VecrvVerifier is VecrvVerifierCore {
    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    address public immutable BLOCK_HASH_ORACLE;

    constructor(address _block_hash_oracle, address _vecrv_oracle)
        VecrvVerifierCore(_vecrv_oracle)
    {
        BLOCK_HASH_ORACLE = _block_hash_oracle;
    }

    /// @param _user User to verify balance for
    /// @param _block_header_rlp The RLP-encoded block header
    /// @param _proof_rlp The state proof of the parameters
    function verifyBalanceByBlockHash(
        address _user,
        bytes memory _block_header_rlp,
        bytes memory _proof_rlp
    ) external {
        RLPReader.RLPItem[] memory proofs = _proof_rlp.toRlpItem().toList();
        require(proofs.length >= 1, "Invalid number of proofs");
        (bytes32 storage_root, uint256 block_number) = _extractAccountStorageRoot(_block_header_rlp, proofs[0]);

        _updateTotal(storage_root, block_number, proofs[1].toList());
        _updateBalance(_user, storage_root, block_number, proofs[2].toList());
    }

    /// @param _user User to verify balance for
    /// @param _block_number Number of the block to use state root hash
    /// @param _proof_rlp The state proof of the parameters
    function verifyBalanceByStateRoot(
        address _user,
        uint256 _block_number,
        bytes memory _proof_rlp
    ) external {
        RLPReader.RLPItem[] memory proofs = _proof_rlp.toRlpItem().toList();
        require(proofs.length >= 1, "Invalid number of proofs");
        bytes32 state_root = IBlockHashOracle(BLOCK_HASH_ORACLE).get_state_root(_block_number);
        bytes32 storage_root = _extractAccountStorageRoot(state_root, proofs[0]);

        _updateTotal(storage_root, _block_number, proofs[1].toList());
        _updateBalance(_user, storage_root, _block_number, proofs[2].toList());
    }

    /// @param _block_header_rlp The RLP-encoded block header
    /// @param _proof_rlp The state proof of the parameters
    function verifyTotalByBlockHash(
        bytes memory _block_header_rlp,
        bytes memory _proof_rlp
    ) external {
        RLPReader.RLPItem[] memory proofs = _proof_rlp.toRlpItem().toList();
        require(proofs.length >= 1, "Invalid number of proofs");
        (bytes32 storage_root, uint256 block_number) = _extractAccountStorageRoot(_block_header_rlp, proofs[0]);

        _updateTotal(storage_root, block_number, proofs[1].toList());
    }

    /// @param _block_number Number of the block to use state root hash
    /// @param _proof_rlp The state proof of the parameters
    function verifyTotalByStateRoot(
        uint256 _block_number,
        bytes memory _proof_rlp
    ) external {
        RLPReader.RLPItem[] memory proofs = _proof_rlp.toRlpItem().toList();
        require(proofs.length >= 1, "Invalid number of proofs");
        bytes32 state_root = IBlockHashOracle(BLOCK_HASH_ORACLE).get_state_root(_block_number);
        bytes32 storage_root = _extractAccountStorageRoot(state_root, proofs[0]);

        _updateTotal(storage_root, _block_number, proofs[1].toList());
    }

    function _extractAccountStorageRoot(
        bytes memory _block_header_rlp,
        RLPReader.RLPItem memory account_proof
    ) internal returns (bytes32, uint256) {
        Verifier.BlockHeader memory block_header = Verifier.parseBlockHeader(_block_header_rlp);
        require(block_header.hash != bytes32(0), "Invalid blockhash");
        require(
            block_header.hash == IBlockHashOracle(BLOCK_HASH_ORACLE).get_block_hash(block_header.number),
            "Blockhash mismatch"
        );
        return (_extractAccountStorageRoot(block_header.stateRootHash, account_proof), block_header.number);
    }
}

// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

import {RLPReader} from "contracts/RLPReader.sol";
import {StateProofVerifier as Verifier} from "contracts/libs/StateProofVerifier.sol";


interface IVecrvOracle {
    struct Point {
        int128 bias;
        int128 slope;
        uint256 ts;
        uint256 blk;
    }

    struct LockedBalance {
        int128 amount;
        uint256 end;
    }

    function update_balance(
        address _user,
        uint256 _user_point_epoch,
        Point memory _user_point_history,
        LockedBalance memory _locked,
        uint256 block_number
    ) external;

    function update_total(
        uint256 _epoch,
        Point memory _point_history,
        int128[] memory _slope_changes,
        uint256 block_number
    ) external;
}

// @dev Base here refers to the fact that this is a base
// contract that is inherited by other contracts and not
// a contract related to the Base L2.
abstract contract VecrvVerifierCore {
    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    uint256 private constant WEEK = 7 * 86400;
    uint256 public constant MIN_SLOPE_CHANGES_CNT = 4; // 1 month

    address private constant VOTING_ESCROW = 0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2;
    bytes32 private constant VOTING_ESCROW_HASH = keccak256(abi.encodePacked(VOTING_ESCROW));

    uint256 private constant EPOCH_SLOT = 3;
    uint256 private constant USER_POINT_EPOCH_SLOT = 6;
    uint256 private constant POINT_HISTORY_SLOT = 4;
    uint256 private constant USER_POINT_HISTORY_SLOT = 5;
    uint256 private constant LOCKED_BALANCE_SLOT = 2;
    uint256 private constant SLOPE_CHANGES_SLOT = 7;

    // update balance
    uint256 private constant USER_POINT_EPOCH_PROOF_I = 0;
    uint256 private constant USER_POINT_HISTORY_PROOF_I = USER_POINT_EPOCH_PROOF_I + 1;
    uint256 private constant LOCKED_BALANCE_PROOF_I = USER_POINT_HISTORY_PROOF_I + 4;

    // update total
    uint256 private constant EPOCH_PROOF_I = 0;
    uint256 private constant POINT_HISTORY_PROOF_I = EPOCH_PROOF_I + 1;
    uint256 private constant SLOPE_CHANGES_PROOF_I = POINT_HISTORY_PROOF_I + 4;

    address public immutable VE_ORACLE;

    constructor(address _ve_oracle) {
        VE_ORACLE = _ve_oracle;
    }

    /// @dev Update total parameters with proofs
    function _updateTotal(
        bytes32 storageRoot,
        uint256 block_number,
        RLPReader.RLPItem[] memory proofs
    ) internal {
        require(proofs.length >= SLOPE_CHANGES_PROOF_I + MIN_SLOPE_CHANGES_CNT, "Invalid number of total proofs");

        // Extract slot values
        uint256 epoch = Verifier.extractSlotValueFromProof(
            keccak256(abi.encode(EPOCH_SLOT)),
            storageRoot,
            proofs[EPOCH_PROOF_I].toList()
        ).value;
        IVecrvOracle.Point memory point_history = _extract_point(
            POINT_HISTORY_PROOF_I,
            keccak256(abi.encode(uint256(keccak256(abi.encode(POINT_HISTORY_SLOT))) + epoch)),
            storageRoot,
            proofs
        );
        uint256 start = WEEK + point_history.ts / WEEK * WEEK;
        int128[] memory slope_changes = new int128[](proofs.length - SLOPE_CHANGES_PROOF_I);
        for (uint256 i = 0; i < proofs.length - SLOPE_CHANGES_PROOF_I; ++i) {
            slope_changes[i] = int128(int256(Verifier.extractSlotValueFromProof(
                keccak256(abi.encode(keccak256(abi.encode(SLOPE_CHANGES_SLOT, start + i * WEEK)))),
                storageRoot,
                proofs[SLOPE_CHANGES_PROOF_I + i].toList()
            ).value));
        }

        return IVecrvOracle(VE_ORACLE).update_total(
            epoch,
            point_history,
            slope_changes,
            block_number
        );
    }

    /// @dev Update user's balance with proofs
    function _updateBalance(
        address user,
        bytes32 storageRoot,
        uint256 block_number,
        RLPReader.RLPItem[] memory proofs
    ) internal {
        require(proofs.length == LOCKED_BALANCE_PROOF_I + 2, "Invalid number of balance proofs");

        // Extract slot values
        uint256 user_point_epoch = Verifier.extractSlotValueFromProof(
            keccak256(
                abi.encode(keccak256(abi.encode(USER_POINT_EPOCH_SLOT, user)))
            ),
            storageRoot,
            proofs[USER_POINT_EPOCH_PROOF_I].toList()
        ).value;
        IVecrvOracle.Point memory user_point_history = _extract_point(
            USER_POINT_HISTORY_PROOF_I,
            keccak256(abi.encode(uint256(keccak256(abi.encode(keccak256(abi.encode(USER_POINT_HISTORY_SLOT, user))))) + user_point_epoch)),
            storageRoot,
            proofs
        );
        IVecrvOracle.LockedBalance memory locked = _extract_locked_balance(
            LOCKED_BALANCE_PROOF_I,
            keccak256(abi.encode(keccak256(abi.encode(LOCKED_BALANCE_SLOT, user)))),
            storageRoot,
            proofs
        );

        return IVecrvOracle(VE_ORACLE).update_balance(
            user,
            user_point_epoch,
            user_point_history,
            locked,
            block_number
        );
    }

    function _extract_point(uint256 proof_i, bytes32 slot, bytes32 storageRoot, RLPReader.RLPItem[] memory proofs) internal returns (IVecrvOracle.Point memory p) {
        p.bias = int128(int256(Verifier.extractSlotValueFromProof(keccak256(abi.encode(slot)), storageRoot, proofs[proof_i].toList()).value));
        p.slope = int128(int256(Verifier.extractSlotValueFromProof(keccak256(abi.encode(uint256(slot) + 1)), storageRoot, proofs[proof_i + 1].toList()).value));
        p.ts = Verifier.extractSlotValueFromProof(keccak256(abi.encode(uint256(slot) + 2)), storageRoot, proofs[proof_i + 2].toList()).value;
        p.blk = Verifier.extractSlotValueFromProof(keccak256(abi.encode(uint256(slot) + 3)), storageRoot, proofs[proof_i + 3].toList()).value;
    }

    function _extract_locked_balance(uint256 proof_i, bytes32 slot, bytes32 storageRoot, RLPReader.RLPItem[] memory proofs) internal returns (IVecrvOracle.LockedBalance memory lb) {
        lb.amount = int128(int256(Verifier.extractSlotValueFromProof(keccak256(abi.encode(slot)), storageRoot, proofs[proof_i].toList()).value));
        lb.end = Verifier.extractSlotValueFromProof(keccak256(abi.encode(uint256(slot) + 1)), storageRoot, proofs[proof_i + 1].toList()).value;
    }

    function _extractAccountStorageRoot(
        bytes32 state_root_hash,
        RLPReader.RLPItem memory account_proof
    ) internal returns (bytes32) {
        Verifier.Account memory account = Verifier.extractAccountFromProof(
            VOTING_ESCROW_HASH,
            state_root_hash,
            account_proof.toList()
        );
        require(account.exists, "VotingEscrow account does not exist");
        return account.storageRoot;
    }
}

// SPDX-License-Identifier: Apache-2.0

/*
 * @author Hamdi Allam [email protected]
 * Please reach out with any questions or concerns
 */
pragma solidity >=0.5.10 <=0.8.18;

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 {
        uint256 len;
        uint256 memPtr;
    }

    struct Iterator {
        RLPItem item; // Item that's being iterated over.
        uint256 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));

        uint256 ptr = self.nextPtr;
        uint256 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) {
        uint256 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));

        uint256 ptr = self.memPtr + _payloadOffset(self.memPtr);
        return Iterator(self, ptr);
    }

    /*
     * @param the RLP item.
     */
    function rlpLen(RLPItem memory item) internal pure returns (uint256) {
        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 (uint256, uint256) {
        uint256 offset = _payloadOffset(item.memPtr);
        uint256 memPtr = item.memPtr + offset;
        uint256 len = item.len - offset; // data length
        return (memPtr, len);
    }

    /*
     * @param the RLP item.
     */
    function payloadLen(RLPItem memory item) internal pure returns (uint256) {
        (, uint256 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));

        uint256 items = numItems(item);
        RLPItem[] memory result = new RLPItem[](items);

        uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 dataLen;
        for (uint256 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;
        uint256 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) {
        (uint256 memPtr, uint256 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;

        uint256 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);
        uint256 result;
        uint256 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 (uint256) {
        require(item.len > 0 && item.len <= 33);

        (uint256 memPtr, uint256 len) = payloadLocation(item);

        uint256 result;
        assembly {
            result := mload(memPtr)

            // shift 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 (uint256) {
        // one byte prefix
        require(item.len == 33);

        uint256 result;
        uint256 memPtr = item.memPtr + 1;
        assembly {
            result := mload(memPtr)
        }

        return result;
    }

    function toBytes(RLPItem memory item) internal pure returns (bytes memory) {
        require(item.len > 0);

        (uint256 memPtr, uint256 len) = payloadLocation(item);
        bytes memory result = new bytes(len);

        uint256 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 (uint256) {
        if (item.len == 0) return 0;

        uint256 count = 0;
        uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr);
        uint256 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(uint256 memPtr) private pure returns (uint256) {
        uint256 itemLen;
        uint256 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(uint256 memPtr) private pure returns (uint256) {
        uint256 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(uint256 src, uint256 dest, uint256 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
            uint256 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.18;

import {MerklePatriciaProofVerifier} from "contracts/libs/MerklePatriciaProofVerifier.sol";
import {RLPReader} from "contracts/RLPReader.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
pragma solidity 0.8.18;

import {RLPReader} from "contracts/RLPReader.sol";

/**
 * Copied from https://github.com/lidofinance/curve-merkle-oracle/blob/1033b3e/contracts/MerklePatriciaProofVerifier.sol
 * with minor code style-related modifications and solidity version constraints loosened.
 *
 * Copied from https://github.com/lorenzb/proveth/blob/c74b20e/onchain/ProvethVerifier.sol
 * with minor performance and code style-related modifications.
 */
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();
                    }

                    // Sanity
                    if (i == stack.length - 1) {
                        // need to process the child now
                        revert();
                    }
                } 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": "paris",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "libraries": {},
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_block_hash_oracle","type":"address"},{"internalType":"address","name":"_vecrv_oracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BLOCK_HASH_ORACLE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_SLOPE_CHANGES_CNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VE_ORACLE","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"verifyBalanceByBlockHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_block_number","type":"uint256"},{"internalType":"bytes","name":"_proof_rlp","type":"bytes"}],"name":"verifyBalanceByStateRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_block_header_rlp","type":"bytes"},{"internalType":"bytes","name":"_proof_rlp","type":"bytes"}],"name":"verifyTotalByBlockHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_block_number","type":"uint256"},{"internalType":"bytes","name":"_proof_rlp","type":"bytes"}],"name":"verifyTotalByStateRoot","outputs":[],"stateMutability":"nonpayable","type":"function"}]

0x60c06040523480156200001157600080fd5b50604051620022f8380380620022f8833981016040819052620000349162000069565b6001600160a01b039081166080521660a052620000a1565b80516001600160a01b03811681146200006457600080fd5b919050565b600080604083850312156200007d57600080fd5b62000088836200004c565b915062000098602084016200004c565b90509250929050565b60805160a05161220f620000e96000396000818160a20152818161023a0152818161033c015261064901526000818161011c01528181610a070152610ce5015261220f6000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80636b13273d1161005b5780636b13273d146100f1578063923bbb2314610104578063b8b9a65c14610117578063db51cbab1461013e57600080fd5b806306ca798614610082578063082e7b411461009d5780631282ff57146100dc575b600080fd5b61008a600481565b6040519081526020015b60405180910390f35b6100c47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610094565b6100ef6100ea366004611d36565b610151565b005b6100ef6100ff366004611d9a565b6101f0565b6100ef610112366004611dee565b6102f2565b6100c47f000000000000000000000000000000000000000000000000000000000000000081565b6100ef61014c366004611e45565b610410565b600061016461015f83610497565b6104c4565b90506001815110156101915760405162461bcd60e51b815260040161018890611eaf565b60405180910390fd5b6000806101b885846000815181106101ab576101ab611ee6565b60200260200101516105da565b915091506101e982826101e4866001815181106101d7576101d7611ee6565b60200260200101516104c4565b61071f565b5050505050565b60006101fe61015f83610497565b90506001815110156102225760405162461bcd60e51b815260040161018890611eaf565b60405162dfe68160e41b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630dfe681090602401602060405180830381865afa158015610289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ad9190611efc565b905060006102d582846000815181106102c8576102c8611ee6565b6020026020010151610a7d565b90506101e981866101e4866001815181106101d7576101d7611ee6565b600061030061015f83610497565b90506001815110156103245760405162461bcd60e51b815260040161018890611eaf565b60405162dfe68160e41b8152600481018490526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630dfe681090602401602060405180830381865afa15801561038b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103af9190611efc565b905060006103ca82846000815181106102c8576102c8611ee6565b90506103e781866101e4866001815181106101d7576101d7611ee6565b610408868287610403876002815181106101d7576101d7611ee6565b610b38565b505050505050565b600061041e61015f83610497565b90506001815110156104425760405162461bcd60e51b815260040161018890611eaf565b60008061045c85846000815181106101ab576101ab611ee6565b9150915061047b82826101e4866001815181106101d7576101d7611ee6565b610408868383610403876002815181106101d7576101d7611ee6565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b60606104cf82610d22565b6104d857600080fd5b60006104e383610d5d565b905060008167ffffffffffffffff81111561050057610500611c93565b60405190808252806020026020018201604052801561054557816020015b604080518082019091526000808252602082015281526020019060019003908161051e5790505b50905060006105578560200151610de2565b85602001516105669190611f2b565b90506000805b848110156105cf5761057d83610e64565b91506040518060400160405280838152602001848152508482815181106105a6576105a6611ee6565b60209081029190910101526105bb8284611f2b565b9250806105c781611f3e565b91505061056c565b509195945050505050565b60008060006105e885610f0d565b805190915061062d5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840c4d8dec6d6d0c2e6d607b1b6044820152606401610188565b6040818101519051639724283f60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639724283f90602401602060405180830381865afa158015610698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bc9190611efc565b8151146107005760405162461bcd60e51b8152602060048201526012602482015271084d8dec6d6d0c2e6d040dad2e6dac2e8c6d60731b6044820152606401610188565b61070e816020015185610a7d565b816040015192509250509250929050565b600461072d60006001611f2b565b610738906004611f2b565b6107429190611f2b565b815110156107925760405162461bcd60e51b815260206004820152601e60248201527f496e76616c6964206e756d626572206f6620746f74616c2070726f6f667300006044820152606401610188565b60006107dd60036040516020016107ab91815260200190565b60405160208183030381529060405280519060200120856107d8856000815181106101d7576101d7611ee6565b610fe9565b60200151905060006108546107f3826001611f2b565b60408051600460208201528591015b6040516020818303038152906040528051906020012060001c6108259190611f2b565b60405160200161083791815260200190565b60405160208183030381529060405280519060200120878661106d565b9050600062093a8080836040015161086c9190611f6d565b6108769190611f81565b6108839062093a80611f2b565b90506000610892816001611f2b565b61089d906004611f2b565b85516108a99190611f98565b67ffffffffffffffff8111156108c1576108c1611c93565b6040519080825280602002602001820160405280156108ea578160200160208202803683370190505b50905060005b6108fc60006001611f2b565b610907906004611f2b565b86516109139190611f98565b8110156109ef576109b4600761092c62093a8084611f81565b6109369086611f2b565b60408051602081019390935282015260600160408051601f198184030181528282528051602091820120908301520160405160208183030381529060405280519060200120896107d889856000600161098f9190611f2b565b61099a906004611f2b565b6109a49190611f2b565b815181106101d7576101d7611ee6565b602001518282815181106109ca576109ca611ee6565b6020026020010190600f0b9081600f0b81525050806109e890611f3e565b90506108f0565b506040516367baa12b60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063cf75425690610a42908790879086908c90600401611fab565b600060405180830381600087803b158015610a5c57600080fd5b505af1158015610a70573d6000803e3d6000fd5b5050505050505050505050565b604051732f9daeff5bd9466debfd5d3c4b1f7101524a715160611b60208201526000908190610ace906034016040516020818303038152906040528051906020012085610ac9866104c4565b6111db565b8051909150610b2b5760405162461bcd60e51b815260206004820152602360248201527f566f74696e67457363726f77206163636f756e7420646f6573206e6f742065786044820152621a5cdd60ea1b6064820152608401610188565b6060015190505b92915050565b610b4460006001611f2b565b610b4f906004611f2b565b610b5a906002611f2b565b815114610ba95760405162461bcd60e51b815260206004820181905260248201527f496e76616c6964206e756d626572206f662062616c616e63652070726f6f66736044820152606401610188565b6000610bf6600686604051602001610bd49291909182526001600160a01b0316602082015260400190565b60408051601f19818403018152828252805160209182012090830152016107ab565b6020015190506000610c55610c0c826001611f2b565b83600589604051602001610c339291909182526001600160a01b0316602082015260400190565b60408051601f1981840301815282825280516020918201209083015201610802565b90506000610ccb610c67826001611f2b565b610c72906004611f2b565b60408051600260208201526001600160a01b038b169181019190915260600160408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001208887611301565b604051639903dcd960e01b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639903dcd990610a42908a908790879087908c90600401612039565b80516000908103610d3557506000919050565b6020820151805160001a9060c0821015610d53575060009392505050565b5060019392505050565b80516000908103610d7057506000919050565b600080610d808460200151610de2565b8460200151610d8f9190611f2b565b9050600084600001518560200151610da79190611f2b565b90505b80821015610dd957610dbb82610e64565b610dc59083611f2b565b915082610dd181611f3e565b935050610daa565b50909392505050565b8051600090811a6080811015610dfb5750600092915050565b60b8811080610e16575060c08110801590610e16575060f881105b15610e245750600192915050565b60c0811015610e5857610e39600160b86120a6565b610e469060ff1682611f98565b610e51906001611f2b565b9392505050565b610e39600160f86120a6565b80516000908190811a6080811015610e7f5760019150610f06565b60b8811015610ea557610e93608082611f98565b610e9e906001611f2b565b9150610f06565b60c0811015610ed25760b78103600185019450806020036101000a85510460018201810193505050610f06565b60f8811015610ee657610e9360c082611f98565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526000610f6361015f85610497565b9050600b815111610f7357600080fd5b610f9681600381518110610f8957610f89611ee6565b6020026020010151611354565b60208301528051610fb49082906008908110610f8957610f89611ee6565b60408301528051610fd2908290600b908110610f8957610f89611ee6565b606083015250825160209093019290922082525090565b6040805180820190915260008082526020820152600061102b848660405160200161101691815260200190565b604051602081830303815290604052856113a2565b6040805180820190915260008082526020820152909150815115611064576001815261105e61105983610497565b611354565b60208201525b95945050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526110d3846040516020016110a791815260200190565b60405160208183030381529060405280519060200120846107d88589815181106101d7576101d7611ee6565b60200151600f0b81526111246110ea856001611f2b565b6040516020016110fc91815260200190565b60405160208183030381529060405280519060200120846107d8858960016109a49190611f2b565b602090810151600f0b9082015261117961113f856002611f2b565b60405160200161115191815260200190565b60405160208183030381529060405280519060200120846107d8858960026109a49190611f2b565b6020015160408201526111ca611190856003611f2b565b6040516020016111a291815260200190565b60405160208183030381529060405280519060200120846107d8858960036109a49190611f2b565b602001516060820152949350505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152600061121f848660405160200161101691815260200190565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152909150815160000361125f579150610e519050565b600061126d61015f84610497565b9050805160041461127d57600080fd5b600182528051611298908290600090610f8957610f89611ee6565b602083015280516112b69082906001908110610f8957610f89611ee6565b604083015280516112d49082906002908110610f8957610f89611ee6565b606083015280516112f29082906003908110610f8957610f89611ee6565b60808301525095945050505050565b604080518082019091526000808252602082015261132b846040516020016110a791815260200190565b60200151600f0b81526113426110ea856001611f2b565b60209081015190820152949350505050565b80516000901580159061136957508151602110155b61137257600080fd5b60008061137e846117ea565b81519193509150602082101561139a5760208290036101000a90045b949350505050565b606060006113b1846000611831565b905060008060606113d5604051806040016040528060008152602001600081525090565b8651600003611426577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421891461140a57600080fd5b50506040805160008152602081019091529350610e5192505050565b60005b87518110156117dd5780158015611468575061146488828151811061145057611450611ee6565b602002602001015160208101519051902090565b8a14155b1561147257600080fd5b80158015906114a2575061149e88828151811061149157611491611ee6565b60200260200101516119d7565b8414155b156114ac57600080fd5b6114c18882815181106101d7576101d7611ee6565b9250825160020361166d57600060606114fb6114f6866000815181106114e9576114e9611ee6565b6020026020010151611a31565b611aaf565b9092509050600061150d888a84611b4a565b90506115198189611f2b565b9750815181101561157c5760018b516115329190611f98565b84101561153e57600080fd5b60005b6040519080825280601f01601f19166020018201604052801561156b576020820181803683370190505b509950505050505050505050610e51565b82156115e25760018b516115909190611f98565b84101561159c57600080fd5b88518810156115ac576000611541565b856001815181106115bf576115bf611ee6565b602002602001015194506115d285611a31565b9950505050505050505050610e51565b60018b516115f09190611f98565b84036115fb57600080fd5b61161e8660018151811061161157611611611ee6565b6020026020010151610d22565b61164c576116458660018151811061163857611638611ee6565b6020026020010151611bd5565b9650611665565b6116628660018151811061145057611450611ee6565b96505b5050506117cb565b82516011036117cb578551851461178f57600086868151811061169257611692611ee6565b016020015160f81c90506116a7600187611f2b565b955060108160ff16106116b957600080fd5b6116de848260ff16815181106116d1576116d1611ee6565b6020026020010151611bed565b1561171a57600189516116f19190611f98565b82146116fc57600080fd5b50506040805160008152602081019091529550610e51945050505050565b611732848260ff168151811061161157611611611ee6565b6117555761174e848260ff168151811061163857611638611ee6565b9450611770565b61176d848260ff168151811061145057611450611ee6565b94505b6001895161177e9190611f98565b820361178957600080fd5b506117cb565b6001885161179d9190611f98565b81146117a857600080fd5b6117be836010815181106114e9576114e9611ee6565b9650505050505050610e51565b806117d581611f3e565b915050611429565b5050505050509392505050565b60008060006117fc8460200151610de2565b905060008185602001516118109190611f2b565b905060008286600001516118249190611f98565b9196919550909350505050565b6060600083511161184157600080fd5b6000835160026118519190611f81565b90508083111561186057600080fd5b61186a8382611f98565b90508067ffffffffffffffff81111561188557611885611c93565b6040519080825280601f01601f1916602001820160405280156118af576020820181803683370190505b5091506000835b6118c08386611f2b565b8110156119be576118d26002826120bf565b60000361193e576004866118e7600284611f6d565b815181106118f7576118f7611ee6565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061192257611922611ee6565b60200101906001600160f81b031916908160001a90535061199f565b60008661194c600284611f6d565b8151811061195c5761195c611ee6565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061198757611987611ee6565b60200101906001600160f81b031916908160001a9053505b6119aa600183611f2b565b91506119b7600182611f2b565b90506118b6565b50825181146119cf576119cf6120d3565b505092915050565b60006020826000015110156119f457602082015182519020610b32565b602082015182519020604051602001611a0f91815260200190565b604051602081830303815290604052805190602001209050919050565b919050565b8051606090611a3f57600080fd5b600080611a4b846117ea565b9150915060008167ffffffffffffffff811115611a6a57611a6a611c93565b6040519080825280601f01601f191660200182016040528015611a94576020820181803683370190505b50905060208101611aa6848285611c10565b50949350505050565b600060606000835111611ac157600080fd5b6000600484600081518110611ad857611ad8611ee6565b60209101015160f81c901c600f1690506000818103611afd5750600092506002611b34565b81600103611b115750600092506001611b34565b81600203611b255750600192506002611b34565b8160030361007d575060019250825b83611b3f8683611831565b935093505050915091565b6000805b8351611b5a8683611f2b565b108015611b675750825181105b1561139a57828181518110611b7e57611b7e611ee6565b01602001516001600160f81b03191684611b988784611f2b565b81518110611ba857611ba8611ee6565b01602001516001600160f81b03191614611bc3579050610e51565b80611bcd81611f3e565b915050611b4e565b6000806000611be3846117ea565b9020949350505050565b8051600090600114611c0157506000919050565b50602001515160001a60801490565b80600003611c1d57505050565b60208110611c555782518252611c34602084611f2b565b9250611c41602083611f2b565b9150611c4e602082611f98565b9050611c1d565b8015611c8e5760006001611c6a836020611f98565b611c76906101006121cd565b611c809190611f98565b845184518216911916178352505b505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611cba57600080fd5b813567ffffffffffffffff80821115611cd557611cd5611c93565b604051601f8301601f19908116603f01168101908282118183101715611cfd57611cfd611c93565b81604052838152866020858801011115611d1657600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611d4957600080fd5b823567ffffffffffffffff80821115611d6157600080fd5b611d6d86838701611ca9565b93506020850135915080821115611d8357600080fd5b50611d9085828601611ca9565b9150509250929050565b60008060408385031215611dad57600080fd5b82359150602083013567ffffffffffffffff811115611dcb57600080fd5b611d9085828601611ca9565b80356001600160a01b0381168114611a2c57600080fd5b600080600060608486031215611e0357600080fd5b611e0c84611dd7565b925060208401359150604084013567ffffffffffffffff811115611e2f57600080fd5b611e3b86828701611ca9565b9150509250925092565b600080600060608486031215611e5a57600080fd5b611e6384611dd7565b9250602084013567ffffffffffffffff80821115611e8057600080fd5b611e8c87838801611ca9565b93506040860135915080821115611ea257600080fd5b50611e3b86828701611ca9565b60208082526018908201527f496e76616c6964206e756d626572206f662070726f6f66730000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611f0e57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b3257610b32611f15565b600060018201611f5057611f50611f15565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082611f7c57611f7c611f57565b500490565b8082028115828204841417610b3257610b32611f15565b81810381811115610b3257610b32611f15565b600060e082018683526020611fe9818501888051600f0b82526020810151600f0b602083015260408101516040830152606081015160608301525050565b60e060a08501528551918290528086019161010085019060005b81811015612022578451600f0b83529383019391830191600101612003565b50508093505050508260c083015295945050505050565b6001600160a01b038616815260208101859052610120810161208560408301868051600f0b82526020810151600f0b602083015260408101516040830152606081015160608301525050565b8351600f0b60c083015260209093015160e082015261010001529392505050565b60ff8281168282160390811115610b3257610b32611f15565b6000826120ce576120ce611f57565b500690565b634e487b7160e01b600052600160045260246000fd5b600181815b8085111561212457816000190482111561210a5761210a611f15565b8085161561211757918102915b93841c93908002906120ee565b509250929050565b60008261213b57506001610b32565b8161214857506000610b32565b816001811461215e576002811461216857612184565b6001915050610b32565b60ff84111561217957612179611f15565b50506001821b610b32565b5060208310610133831016604e8410600b84101617156121a7575081810a610b32565b6121b183836120e9565b80600019048211156121c5576121c5611f15565b029392505050565b6000610e51838361212c56fea2646970667358221220bd162171899c822f41b3ae1c9c9b220141e2fe0a42ec2b91b6be0ce23a9d125764736f6c63430008120033000000000000000000000000e35a879e5efb4f1bb7f70dcf3250f2e19f096bd8000000000000000000000000361aa6d20fbf6185490eb2ddf1dd1d3f301c201d

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80636b13273d1161005b5780636b13273d146100f1578063923bbb2314610104578063b8b9a65c14610117578063db51cbab1461013e57600080fd5b806306ca798614610082578063082e7b411461009d5780631282ff57146100dc575b600080fd5b61008a600481565b6040519081526020015b60405180910390f35b6100c47f000000000000000000000000e35a879e5efb4f1bb7f70dcf3250f2e19f096bd881565b6040516001600160a01b039091168152602001610094565b6100ef6100ea366004611d36565b610151565b005b6100ef6100ff366004611d9a565b6101f0565b6100ef610112366004611dee565b6102f2565b6100c47f000000000000000000000000361aa6d20fbf6185490eb2ddf1dd1d3f301c201d81565b6100ef61014c366004611e45565b610410565b600061016461015f83610497565b6104c4565b90506001815110156101915760405162461bcd60e51b815260040161018890611eaf565b60405180910390fd5b6000806101b885846000815181106101ab576101ab611ee6565b60200260200101516105da565b915091506101e982826101e4866001815181106101d7576101d7611ee6565b60200260200101516104c4565b61071f565b5050505050565b60006101fe61015f83610497565b90506001815110156102225760405162461bcd60e51b815260040161018890611eaf565b60405162dfe68160e41b8152600481018490526000907f000000000000000000000000e35a879e5efb4f1bb7f70dcf3250f2e19f096bd86001600160a01b031690630dfe681090602401602060405180830381865afa158015610289573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ad9190611efc565b905060006102d582846000815181106102c8576102c8611ee6565b6020026020010151610a7d565b90506101e981866101e4866001815181106101d7576101d7611ee6565b600061030061015f83610497565b90506001815110156103245760405162461bcd60e51b815260040161018890611eaf565b60405162dfe68160e41b8152600481018490526000907f000000000000000000000000e35a879e5efb4f1bb7f70dcf3250f2e19f096bd86001600160a01b031690630dfe681090602401602060405180830381865afa15801561038b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103af9190611efc565b905060006103ca82846000815181106102c8576102c8611ee6565b90506103e781866101e4866001815181106101d7576101d7611ee6565b610408868287610403876002815181106101d7576101d7611ee6565b610b38565b505050505050565b600061041e61015f83610497565b90506001815110156104425760405162461bcd60e51b815260040161018890611eaf565b60008061045c85846000815181106101ab576101ab611ee6565b9150915061047b82826101e4866001815181106101d7576101d7611ee6565b610408868383610403876002815181106101d7576101d7611ee6565b60408051808201825260008082526020918201528151808301909252825182529182019181019190915290565b60606104cf82610d22565b6104d857600080fd5b60006104e383610d5d565b905060008167ffffffffffffffff81111561050057610500611c93565b60405190808252806020026020018201604052801561054557816020015b604080518082019091526000808252602082015281526020019060019003908161051e5790505b50905060006105578560200151610de2565b85602001516105669190611f2b565b90506000805b848110156105cf5761057d83610e64565b91506040518060400160405280838152602001848152508482815181106105a6576105a6611ee6565b60209081029190910101526105bb8284611f2b565b9250806105c781611f3e565b91505061056c565b509195945050505050565b60008060006105e885610f0d565b805190915061062d5760405162461bcd60e51b8152602060048201526011602482015270092dcecc2d8d2c840c4d8dec6d6d0c2e6d607b1b6044820152606401610188565b6040818101519051639724283f60e01b815260048101919091527f000000000000000000000000e35a879e5efb4f1bb7f70dcf3250f2e19f096bd86001600160a01b031690639724283f90602401602060405180830381865afa158015610698573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106bc9190611efc565b8151146107005760405162461bcd60e51b8152602060048201526012602482015271084d8dec6d6d0c2e6d040dad2e6dac2e8c6d60731b6044820152606401610188565b61070e816020015185610a7d565b816040015192509250509250929050565b600461072d60006001611f2b565b610738906004611f2b565b6107429190611f2b565b815110156107925760405162461bcd60e51b815260206004820152601e60248201527f496e76616c6964206e756d626572206f6620746f74616c2070726f6f667300006044820152606401610188565b60006107dd60036040516020016107ab91815260200190565b60405160208183030381529060405280519060200120856107d8856000815181106101d7576101d7611ee6565b610fe9565b60200151905060006108546107f3826001611f2b565b60408051600460208201528591015b6040516020818303038152906040528051906020012060001c6108259190611f2b565b60405160200161083791815260200190565b60405160208183030381529060405280519060200120878661106d565b9050600062093a8080836040015161086c9190611f6d565b6108769190611f81565b6108839062093a80611f2b565b90506000610892816001611f2b565b61089d906004611f2b565b85516108a99190611f98565b67ffffffffffffffff8111156108c1576108c1611c93565b6040519080825280602002602001820160405280156108ea578160200160208202803683370190505b50905060005b6108fc60006001611f2b565b610907906004611f2b565b86516109139190611f98565b8110156109ef576109b4600761092c62093a8084611f81565b6109369086611f2b565b60408051602081019390935282015260600160408051601f198184030181528282528051602091820120908301520160405160208183030381529060405280519060200120896107d889856000600161098f9190611f2b565b61099a906004611f2b565b6109a49190611f2b565b815181106101d7576101d7611ee6565b602001518282815181106109ca576109ca611ee6565b6020026020010190600f0b9081600f0b81525050806109e890611f3e565b90506108f0565b506040516367baa12b60e11b81526001600160a01b037f000000000000000000000000361aa6d20fbf6185490eb2ddf1dd1d3f301c201d169063cf75425690610a42908790879086908c90600401611fab565b600060405180830381600087803b158015610a5c57600080fd5b505af1158015610a70573d6000803e3d6000fd5b5050505050505050505050565b604051732f9daeff5bd9466debfd5d3c4b1f7101524a715160611b60208201526000908190610ace906034016040516020818303038152906040528051906020012085610ac9866104c4565b6111db565b8051909150610b2b5760405162461bcd60e51b815260206004820152602360248201527f566f74696e67457363726f77206163636f756e7420646f6573206e6f742065786044820152621a5cdd60ea1b6064820152608401610188565b6060015190505b92915050565b610b4460006001611f2b565b610b4f906004611f2b565b610b5a906002611f2b565b815114610ba95760405162461bcd60e51b815260206004820181905260248201527f496e76616c6964206e756d626572206f662062616c616e63652070726f6f66736044820152606401610188565b6000610bf6600686604051602001610bd49291909182526001600160a01b0316602082015260400190565b60408051601f19818403018152828252805160209182012090830152016107ab565b6020015190506000610c55610c0c826001611f2b565b83600589604051602001610c339291909182526001600160a01b0316602082015260400190565b60408051601f1981840301815282825280516020918201209083015201610802565b90506000610ccb610c67826001611f2b565b610c72906004611f2b565b60408051600260208201526001600160a01b038b169181019190915260600160408051601f1981840301815282825280516020918201209083015201604051602081830303815290604052805190602001208887611301565b604051639903dcd960e01b81529091506001600160a01b037f000000000000000000000000361aa6d20fbf6185490eb2ddf1dd1d3f301c201d1690639903dcd990610a42908a908790879087908c90600401612039565b80516000908103610d3557506000919050565b6020820151805160001a9060c0821015610d53575060009392505050565b5060019392505050565b80516000908103610d7057506000919050565b600080610d808460200151610de2565b8460200151610d8f9190611f2b565b9050600084600001518560200151610da79190611f2b565b90505b80821015610dd957610dbb82610e64565b610dc59083611f2b565b915082610dd181611f3e565b935050610daa565b50909392505050565b8051600090811a6080811015610dfb5750600092915050565b60b8811080610e16575060c08110801590610e16575060f881105b15610e245750600192915050565b60c0811015610e5857610e39600160b86120a6565b610e469060ff1682611f98565b610e51906001611f2b565b9392505050565b610e39600160f86120a6565b80516000908190811a6080811015610e7f5760019150610f06565b60b8811015610ea557610e93608082611f98565b610e9e906001611f2b565b9150610f06565b60c0811015610ed25760b78103600185019450806020036101000a85510460018201810193505050610f06565b60f8811015610ee657610e9360c082611f98565b60f78103600185019450806020036101000a855104600182018101935050505b5092915050565b6040805160808101825260008082526020820181905291810182905260608101919091526040805160808101825260008082526020820181905291810182905260608101919091526000610f6361015f85610497565b9050600b815111610f7357600080fd5b610f9681600381518110610f8957610f89611ee6565b6020026020010151611354565b60208301528051610fb49082906008908110610f8957610f89611ee6565b60408301528051610fd2908290600b908110610f8957610f89611ee6565b606083015250825160209093019290922082525090565b6040805180820190915260008082526020820152600061102b848660405160200161101691815260200190565b604051602081830303815290604052856113a2565b6040805180820190915260008082526020820152909150815115611064576001815261105e61105983610497565b611354565b60208201525b95945050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526110d3846040516020016110a791815260200190565b60405160208183030381529060405280519060200120846107d88589815181106101d7576101d7611ee6565b60200151600f0b81526111246110ea856001611f2b565b6040516020016110fc91815260200190565b60405160208183030381529060405280519060200120846107d8858960016109a49190611f2b565b602090810151600f0b9082015261117961113f856002611f2b565b60405160200161115191815260200190565b60405160208183030381529060405280519060200120846107d8858960026109a49190611f2b565b6020015160408201526111ca611190856003611f2b565b6040516020016111a291815260200190565b60405160208183030381529060405280519060200120846107d8858960036109a49190611f2b565b602001516060820152949350505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152600061121f848660405160200161101691815260200190565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152909150815160000361125f579150610e519050565b600061126d61015f84610497565b9050805160041461127d57600080fd5b600182528051611298908290600090610f8957610f89611ee6565b602083015280516112b69082906001908110610f8957610f89611ee6565b604083015280516112d49082906002908110610f8957610f89611ee6565b606083015280516112f29082906003908110610f8957610f89611ee6565b60808301525095945050505050565b604080518082019091526000808252602082015261132b846040516020016110a791815260200190565b60200151600f0b81526113426110ea856001611f2b565b60209081015190820152949350505050565b80516000901580159061136957508151602110155b61137257600080fd5b60008061137e846117ea565b81519193509150602082101561139a5760208290036101000a90045b949350505050565b606060006113b1846000611831565b905060008060606113d5604051806040016040528060008152602001600081525090565b8651600003611426577f56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421891461140a57600080fd5b50506040805160008152602081019091529350610e5192505050565b60005b87518110156117dd5780158015611468575061146488828151811061145057611450611ee6565b602002602001015160208101519051902090565b8a14155b1561147257600080fd5b80158015906114a2575061149e88828151811061149157611491611ee6565b60200260200101516119d7565b8414155b156114ac57600080fd5b6114c18882815181106101d7576101d7611ee6565b9250825160020361166d57600060606114fb6114f6866000815181106114e9576114e9611ee6565b6020026020010151611a31565b611aaf565b9092509050600061150d888a84611b4a565b90506115198189611f2b565b9750815181101561157c5760018b516115329190611f98565b84101561153e57600080fd5b60005b6040519080825280601f01601f19166020018201604052801561156b576020820181803683370190505b509950505050505050505050610e51565b82156115e25760018b516115909190611f98565b84101561159c57600080fd5b88518810156115ac576000611541565b856001815181106115bf576115bf611ee6565b602002602001015194506115d285611a31565b9950505050505050505050610e51565b60018b516115f09190611f98565b84036115fb57600080fd5b61161e8660018151811061161157611611611ee6565b6020026020010151610d22565b61164c576116458660018151811061163857611638611ee6565b6020026020010151611bd5565b9650611665565b6116628660018151811061145057611450611ee6565b96505b5050506117cb565b82516011036117cb578551851461178f57600086868151811061169257611692611ee6565b016020015160f81c90506116a7600187611f2b565b955060108160ff16106116b957600080fd5b6116de848260ff16815181106116d1576116d1611ee6565b6020026020010151611bed565b1561171a57600189516116f19190611f98565b82146116fc57600080fd5b50506040805160008152602081019091529550610e51945050505050565b611732848260ff168151811061161157611611611ee6565b6117555761174e848260ff168151811061163857611638611ee6565b9450611770565b61176d848260ff168151811061145057611450611ee6565b94505b6001895161177e9190611f98565b820361178957600080fd5b506117cb565b6001885161179d9190611f98565b81146117a857600080fd5b6117be836010815181106114e9576114e9611ee6565b9650505050505050610e51565b806117d581611f3e565b915050611429565b5050505050509392505050565b60008060006117fc8460200151610de2565b905060008185602001516118109190611f2b565b905060008286600001516118249190611f98565b9196919550909350505050565b6060600083511161184157600080fd5b6000835160026118519190611f81565b90508083111561186057600080fd5b61186a8382611f98565b90508067ffffffffffffffff81111561188557611885611c93565b6040519080825280601f01601f1916602001820160405280156118af576020820181803683370190505b5091506000835b6118c08386611f2b565b8110156119be576118d26002826120bf565b60000361193e576004866118e7600284611f6d565b815181106118f7576118f7611ee6565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061192257611922611ee6565b60200101906001600160f81b031916908160001a90535061199f565b60008661194c600284611f6d565b8151811061195c5761195c611ee6565b602001015160f81c60f81b60f81c60ff16901c600f1660f81b84838151811061198757611987611ee6565b60200101906001600160f81b031916908160001a9053505b6119aa600183611f2b565b91506119b7600182611f2b565b90506118b6565b50825181146119cf576119cf6120d3565b505092915050565b60006020826000015110156119f457602082015182519020610b32565b602082015182519020604051602001611a0f91815260200190565b604051602081830303815290604052805190602001209050919050565b919050565b8051606090611a3f57600080fd5b600080611a4b846117ea565b9150915060008167ffffffffffffffff811115611a6a57611a6a611c93565b6040519080825280601f01601f191660200182016040528015611a94576020820181803683370190505b50905060208101611aa6848285611c10565b50949350505050565b600060606000835111611ac157600080fd5b6000600484600081518110611ad857611ad8611ee6565b60209101015160f81c901c600f1690506000818103611afd5750600092506002611b34565b81600103611b115750600092506001611b34565b81600203611b255750600192506002611b34565b8160030361007d575060019250825b83611b3f8683611831565b935093505050915091565b6000805b8351611b5a8683611f2b565b108015611b675750825181105b1561139a57828181518110611b7e57611b7e611ee6565b01602001516001600160f81b03191684611b988784611f2b565b81518110611ba857611ba8611ee6565b01602001516001600160f81b03191614611bc3579050610e51565b80611bcd81611f3e565b915050611b4e565b6000806000611be3846117ea565b9020949350505050565b8051600090600114611c0157506000919050565b50602001515160001a60801490565b80600003611c1d57505050565b60208110611c555782518252611c34602084611f2b565b9250611c41602083611f2b565b9150611c4e602082611f98565b9050611c1d565b8015611c8e5760006001611c6a836020611f98565b611c76906101006121cd565b611c809190611f98565b845184518216911916178352505b505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611cba57600080fd5b813567ffffffffffffffff80821115611cd557611cd5611c93565b604051601f8301601f19908116603f01168101908282118183101715611cfd57611cfd611c93565b81604052838152866020858801011115611d1657600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060408385031215611d4957600080fd5b823567ffffffffffffffff80821115611d6157600080fd5b611d6d86838701611ca9565b93506020850135915080821115611d8357600080fd5b50611d9085828601611ca9565b9150509250929050565b60008060408385031215611dad57600080fd5b82359150602083013567ffffffffffffffff811115611dcb57600080fd5b611d9085828601611ca9565b80356001600160a01b0381168114611a2c57600080fd5b600080600060608486031215611e0357600080fd5b611e0c84611dd7565b925060208401359150604084013567ffffffffffffffff811115611e2f57600080fd5b611e3b86828701611ca9565b9150509250925092565b600080600060608486031215611e5a57600080fd5b611e6384611dd7565b9250602084013567ffffffffffffffff80821115611e8057600080fd5b611e8c87838801611ca9565b93506040860135915080821115611ea257600080fd5b50611e3b86828701611ca9565b60208082526018908201527f496e76616c6964206e756d626572206f662070726f6f66730000000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215611f0e57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610b3257610b32611f15565b600060018201611f5057611f50611f15565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082611f7c57611f7c611f57565b500490565b8082028115828204841417610b3257610b32611f15565b81810381811115610b3257610b32611f15565b600060e082018683526020611fe9818501888051600f0b82526020810151600f0b602083015260408101516040830152606081015160608301525050565b60e060a08501528551918290528086019161010085019060005b81811015612022578451600f0b83529383019391830191600101612003565b50508093505050508260c083015295945050505050565b6001600160a01b038616815260208101859052610120810161208560408301868051600f0b82526020810151600f0b602083015260408101516040830152606081015160608301525050565b8351600f0b60c083015260209093015160e082015261010001529392505050565b60ff8281168282160390811115610b3257610b32611f15565b6000826120ce576120ce611f57565b500690565b634e487b7160e01b600052600160045260246000fd5b600181815b8085111561212457816000190482111561210a5761210a611f15565b8085161561211757918102915b93841c93908002906120ee565b509250929050565b60008261213b57506001610b32565b8161214857506000610b32565b816001811461215e576002811461216857612184565b6001915050610b32565b60ff84111561217957612179611f15565b50506001821b610b32565b5060208310610133831016604e8410600b84101617156121a7575081810a610b32565b6121b183836120e9565b80600019048211156121c5576121c5611f15565b029392505050565b6000610e51838361212c56fea2646970667358221220bd162171899c822f41b3ae1c9c9b220141e2fe0a42ec2b91b6be0ce23a9d125764736f6c63430008120033

Block Transaction Gas Used Reward
view all blocks ##produced##

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.