MATIC Price: $0.356391 (-20.98%)
 

Overview

MATIC Balance

Polygon PoS Chain LogoPolygon PoS Chain LogoPolygon PoS Chain Logo0 MATIC

MATIC Value

$0.00

Token Holdings

Sponsored

Transaction Hash
Method
Block
From
To
Submit New T Xs ...602214832024-08-05 11:52:381 min ago1722858758IN
0x45F411ce...C868442b4
0 MATIC0.0024817885.99392006
Submit New T Xs ...602214052024-08-05 11:49:524 mins ago1722858592IN
0x45F411ce...C868442b4
0 MATIC0.00342801118.78078944
Submit New T Xs ...602213272024-08-05 11:47:067 mins ago1722858426IN
0x45F411ce...C868442b4
0 MATIC0.005089176.33404407
Submit New T Xs ...602212502024-08-05 11:43:5810 mins ago1722858238IN
0x45F411ce...C868442b4
0 MATIC0.00433879150.33925836
Submit New T Xs ...602211762024-08-05 11:41:1413 mins ago1722858074IN
0x45F411ce...C868442b4
0 MATIC0.00575554199.42986781
Submit New T Xs ...602210992024-08-05 11:38:3016 mins ago1722857910IN
0x45F411ce...C868442b4
0 MATIC0.00367625127.38227073
Submit New T Xs ...602210222024-08-05 11:35:4618 mins ago1722857746IN
0x45F411ce...C868442b4
0 MATIC0.00498739172.8135282
Submit New T Xs ...602209452024-08-05 11:33:0421 mins ago1722857584IN
0x45F411ce...C868442b4
0 MATIC0.005984207.34608036
Submit New T Xs ...602208682024-08-05 11:30:2024 mins ago1722857420IN
0x45F411ce...C868442b4
0 MATIC0.01170377405.53605558
Submit New Owner...602205452024-08-05 11:18:2236 mins ago1722856702IN
0x45F411ce...C868442b4
0 MATIC0.03150179142.55754335
Submit New T Xs ...602204602024-08-05 11:15:1439 mins ago1722856514IN
0x45F411ce...C868442b4
0 MATIC0.03108002145.21883063
Submit New Owner...602201322024-08-05 11:03:1251 mins ago1722855792IN
0x45F411ce...C868442b4
0 MATIC0.03016549136.51028754
Submit New T Xs ...602200472024-08-05 11:00:1054 mins ago1722855610IN
0x45F411ce...C868442b4
0 MATIC0.0209096397.69853541
Submit New Owner...602197402024-08-05 10:48:461 hr ago1722854926IN
0x45F411ce...C868442b4
0 MATIC0.04379676198.19690851
Submit New T Xs ...602196522024-08-05 10:45:181 hr ago1722854718IN
0x45F411ce...C868442b4
0 MATIC0.06910962322.90895918
Submit New Owner...602193132024-08-05 10:33:081 hr ago1722853988IN
0x45F411ce...C868442b4
0 MATIC0.02833356128.22011852
Submit New T Xs ...602192322024-08-05 10:30:161 hr ago1722853816IN
0x45F411ce...C868442b4
0 MATIC0.04377443204.53240027
Submit New Owner...602189192024-08-05 10:18:381 hr ago1722853118IN
0x45F411ce...C868442b4
0 MATIC0.06768101306.28221456
Submit New T Xs ...602188372024-08-05 10:15:121 hr ago1722852912IN
0x45F411ce...C868442b4
0 MATIC0.0212960399.50393806
Submit New Owner...602185092024-08-05 10:03:341 hr ago1722852214IN
0x45F411ce...C868442b4
0 MATIC0.0205629993.05533304
Submit New T Xs ...602184162024-08-05 10:00:181 hr ago1722852018IN
0x45F411ce...C868442b4
0 MATIC0.03354437156.73328083
Submit New Owner...602181142024-08-05 9:48:322 hrs ago1722851312IN
0x45F411ce...C868442b4
0 MATIC0.02969351134.37440438
Submit New T Xs ...602180192024-08-05 9:45:102 hrs ago1722851110IN
0x45F411ce...C868442b4
0 MATIC0.02988763139.64747733
Submit New Owner...602177202024-08-05 9:34:022 hrs ago1722850442IN
0x45F411ce...C868442b4
0 MATIC0.0217889398.60319357
Submit New T Xs ...602176272024-08-05 9:30:122 hrs ago1722850212IN
0x45F411ce...C868442b4
0 MATIC0.0160400774.94592273
View all transactions

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Updates

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion
File 1 of 17 : Updates.sol
// SPDX-License-Identifier: BUSL-1.1
// License details specified at address returned by calling the function: license()
pragma solidity =0.8.11;

/**
 @title Manages Updates of Multiverse properties and Ownership
 @author Freeverse.io, www.freeverse.io
*/

import "../interfaces/IWriter.sol";
import "../interfaces/IStorageGetters.sol";
import "../interfaces/IInfo.sol";
import "../interfaces/IUpdates.sol";
import "../interfaces/IStakers.sol";

import "../pure/Messages.sol";
import "../pure/MerkleSerialized.sol";

contract Updates is IUpdates, Messages, MerkleSerialized {
    /// @inheritdoc IUpdates
    address public immutable _sto;

    /// @inheritdoc IUpdates
    address public immutable _writer;

    /// @inheritdoc IUpdates
    address public immutable _info;

    /// @inheritdoc IUpdates
    uint32 constant public OWNERSHIP_TXFORMAT_VERSION = 1;

    // temporary variable used to maintain signature 
    // of functions being deprecated
    bool _dummy;

    modifier onlyUniversesRelayer() {
        require(
            msg.sender == IStorageGetters(_sto).universesRelayer(),
            "Only relay of universes is authorized."
        );
        _;
    }

    modifier onlyTXRelayer() {
        require(
            msg.sender == IStorageGetters(_sto).txRelayer(),
            "Only relay of TXs is authorized."
        );
        _;
    }

    modifier onlySuperUser() {
        require(
            msg.sender == IStorageGetters(_sto).superUser(),
            "Only superUser is authorized."
        );
        _;
    }

    constructor(
        address storageAddress,
        address writer,
        address info
    ) {
        IInfo(info).assertValidStorageExtension();
        _sto = storageAddress;
        _writer = writer;
        _info = info;
        emit OwnershipTxFormatVersion(OWNERSHIP_TXFORMAT_VERSION);
    }

    /// @inheritdoc IUpdates
    function license() external view returns (string memory) {
        return IStorageGetters(_sto).license();
    }

    /**
     * @notice Sets a new Universe root
     * @param universeIdx the idx of the Universe
     * @param newRoot the new root of the Universe
     * @param prevTransRoot the previous root of the Universe
     * @param signature the signature of the authorized relayer
     * @param ipfsCid the IPFS address where data can be fetched
     */
    function setNewUniverseRoot(
        uint256 universeIdx,
        bytes32 newRoot,
        bytes32 prevTransRoot,
        bytes calldata signature,
        string calldata ipfsCid
    ) public onlyUniversesRelayer {
        require(
            !IStorageGetters(_sto).universeIsClosed(universeIdx),
            "setNewUniverseRoot: universe already closed"
        );
        require(
            prevTransRoot ==
                IStorageGetters(_sto).universeRootCurrent(universeIdx),
            "prevTransRoot does not match"
        );
        // If relayer is not authorized, check universe owner signature
        if (!IStorageGetters(_sto).universeAuthorizesRelay(universeIdx)) {
            bytes32 msgHash = prefixed(
                keccak256(abi.encode(newRoot, prevTransRoot))
            );
            require(
                IStorageGetters(_sto).universeOwner(universeIdx) ==
                    recoverAddrFromBytes(msgHash, signature),
                "universe root update signature not correct"
            );
        }
        uint256 newVerse = IWriter(_writer).addUniverseRoot(
            universeIdx,
            newRoot,
            block.timestamp
        );
        emit NewUniverseRoot(universeIdx, newRoot, newVerse, ipfsCid);
    }

    /**
     * @notice Sets a new Universe root at verse
     * @param verse the next universe Verse
     * @param universeIdx the idx of the Universe
     * @param newRoot the new root of the Universe
     * @param prevTransRoot the previous root of the Universe
     * @param signature the signature of the authorized relayer
     * @param ipfsCid the IPFS address where data can be fetched
     */
    function submitNewUniverseRoot(
        uint256 verse,
        uint256 universeIdx,
        bytes32 newRoot,
        bytes32 prevTransRoot,
        bytes calldata signature,
        string calldata ipfsCid
    ) external onlyUniversesRelayer {
        require(
            !IStorageGetters(_sto).universeIsClosed(universeIdx),
            "setNewUniverseRoot: universe already closed"
        );
        require(
            prevTransRoot ==
                IStorageGetters(_sto).universeRootCurrent(universeIdx),
            "prevTransRoot does not match"
        );
        require(
            IInfo(_info).isReadyForUniverseRootSubmission(universeIdx),
            "not ready for universe root submission: verse not settled"
        );
        // If relayer is not authorized, check universe owner signature
        if (!IStorageGetters(_sto).universeAuthorizesRelay(universeIdx)) {
            bytes32 msgHash = prefixed(
                keccak256(abi.encode(newRoot, prevTransRoot))
            );
            require(
                IStorageGetters(_sto).universeOwner(universeIdx) ==
                    recoverAddrFromBytes(msgHash, signature),
                "universe root update signature not correct"
            );
        }
        uint256 newVerse = IWriter(_writer).addUniverseRoot(
            universeIdx,
            newRoot,
            block.timestamp
        );
        require(verse == newVerse, "error: incorrect universe verse");
        emit NewUniverseRoot(universeIdx, newRoot, newVerse, ipfsCid);
    }

    /**
     * @notice Submission of new TXs batch
     * @param verse The verse that will open for the L2 nodes to process
     * @param txRoot The root summarizing the TX batch
     * @param nTXs The number of TXs included in the batch
     * @param txFormatVersion The version of the txFormat used
     * @param ipfsCid The IPFS address where the raw data can be obtained
     */
    function submitNewTXsRoot(
        uint256 verse,
        bytes32 txRoot,
        uint256 nTXs,
        uint32 txFormatVersion,
        string calldata ipfsCid
    ) external onlyTXRelayer {
        require(
            txFormatVersion == OWNERSHIP_TXFORMAT_VERSION,
            "Updates::submitNewTXsRoot: incorrect txFormatVersion"
        );
        require(
            IStorageGetters(_sto).txRootsCurrentVerse() + 1 == verse,
            "error: submitNewTXsRoot for an incorrect verse"
        );
        (bool isReady, uint8 actualLevel) = IInfo(_info)
            .isReadyForTXSubmission();
        require(
            isReady,
            "not ready to accept new TX submission, verse not settled"
        );
        require(
            (actualLevel == 1) || (actualLevel == 2),
            "past verse ended up settling in incorrect level"
        );
        if (nTXs == 0) {
            require(
                txRoot == bytes32(0),
                "in a verse with no TXs, the TXRoot must be null"
            );
        }
        // stores txRoot, timestamp, and (implicitly) increments verse (which equals the length of _txBatches):
        uint8 levelsPerChallenge = IStorageGetters(_sto)
            .nLevelsPerChallengeNextVerses();
        uint8 levelVeriableByBC = computeLevelVerifiableOnChain(
            nTXs,
            2**uint256(levelsPerChallenge)
        );
        uint256 txVerse = IWriter(_writer).addTXRoot(
            txRoot,
            block.timestamp,
            nTXs,
            actualLevel,
            levelVeriableByBC
        );
        if (txVerse > 1) {
            IWriter(_writer).finalize();
        }
        emit NewTXsRoot(txRoot, nTXs, levelsPerChallenge, txVerse, ipfsCid);
    }

    /// @inheritdoc IUpdates
    function submitNewOwnershipRoot(uint256 verse, bytes32 ownershipRoot, uint32 txFormatVersion)
        external
    {   

        require(
            txFormatVersion == OWNERSHIP_TXFORMAT_VERSION,
            "Updates::submitNewOwnershipRoot: incorrect txFormatVersion"
        );
        require(
            IStorageGetters(_sto).txRootsCurrentVerse() == verse,
            "error: submitNewOwnershipRoot for an incorrect verse"
        );
        // call for governance is two different roots are received during challenge period: 
        if (
            IInfo(_info).isReadyForChallenge() && 
            (ownershipRoot != IStorageGetters(_sto).challengesOwnershipRoot(0))
        ) {
            address stakers =  IStorageGetters(_sto).stakers();
            require(
                IStakers(stakers).isStaker(msg.sender),
                "Updates::submitNewOwnershipRoot: staker not registered"
            );
            IWriter(_writer).activateGovernance();
            emit OwnershipRootMismatch(verse, ownershipRoot);
            _bypassCurrentVerse(verse);
            return;
        }
        require(
            isReadyForOwnershipSubmission(),
            "not ready for ownership submission: verse not settled or new TXs not submitted yet"
        );
        uint256 ownVerse = IWriter(_writer).addOwnershipRoot(ownershipRoot, block.timestamp);
        IWriter(_writer).addChallenge(0, msg.sender); // this guarantees that only a staker could have done this submission
        emit NewOwnershipRoot(ownershipRoot, ownVerse);
    }

    /**
     * @notice After governance action, it bypasses the current verse
     *  by not processing any of the submitted TXs, and duplicating the
     *  ownership root settled from the previous verse.
     * @param verse - the current verse; the provision of this param is required
     *  to avoid replay attacks.
     */
    function _bypassCurrentVerse(uint256 verse) private
    {
        require(
            IStorageGetters(_sto).txRootsCurrentVerse() == verse,
            "Updates::_bypassCurrentVerse: incorrect provided verse"
        );
        bool isOwnershipRootSubmitted = verse == IStorageGetters(_sto).ownershipCurrentVerse();
        if (!isOwnershipRootSubmitted) {
            address dummyStaker = address(0);
            uint256 txSubmissionTime = IStorageGetters(_sto).txSubmissionTimeCurrent();
            _addDummyOwnershipRoot(dummyStaker, txSubmissionTime+1);
        }
        bytes32 ownershipRootPrevVerse = IStorageGetters(_sto).ownershipRootAtVerse(verse - 1);
        IWriter(_writer).setProposedOwnershipToPrevVerse(ownershipRootPrevVerse);
        IWriter(_writer).storeBypassedVerse(verse);
        emit BypassVerse(verse);
    }
    
      /**
     * @notice deactivates Governance
     * @dev Requires that the system is in awaitingGovernance
     * @param txVerse - the current txVerse; the provision of this param is required
     *  to avoid replay attacks.
     */
    function deactivateGovernance(uint256 txVerse) external onlySuperUser
    {   
        require(
            IStorageExtension(_info).isAwaitingGovernance(),
            "Updates::deactivateGovernance: system not awaiting for Governance"
        );
        require(
            IStorageGetters(_sto).txRootsCurrentVerse() == txVerse,
            "Updates::deactivateGovernance: incorrect provided verse"
        );
        IWriter(_writer).deactivateGovernance();
    }

    /**
     * @notice Bypasses the current universe verse by setting the root of the previous verse as root of the current verse 
     * and adding universe verses in corresponding claim
     * @dev Requires that the system is in awaitingGovernance
     * @param verse - universe verse that is bypassed
     * @param universeIdx - universe index
     */
    function bypassCurrentUniverseVerse(
        uint256 universeIdx,
        uint256 verse
    ) external onlySuperUser {
        require(
            IStorageExtension(_info).isAwaitingGovernance(),
            "Updates::bypassCurrentUniverseVerse: system not awaiting for Governance"
        );
        require(
            IStorageGetters(_sto).universeVerse(universeIdx) == verse,
            "Updates::bypassCurrentUniverseVerse: incorrect provided verse"
        );
        bytes32 universeRootPrevVerse = IStorageGetters(_sto)
            .universeRootAtVerse(universeIdx, verse - 1);
        uint256 universeRootPrevTimestamp = IStorageGetters(_sto)
            .universeRootSubmissionTimeAtVerse(universeIdx, verse - 1);
        IWriter(_writer).popUniverseRoot(universeIdx);
        IWriter(_writer).addUniverseRoot(
            universeIdx,
            universeRootPrevVerse,
            universeRootPrevTimestamp
        );
        IWriter(_writer).storeBypassedUniverseVerse(universeIdx, verse);
        emit BypassUniverseVerse(universeIdx, verse);
    }

    /**
     * @notice After reception of a NewTXs transaction, the data happens
     *  not to be available in IPFS, making new ownership computation impossible
     * @dev Requires that the system is in awaiting ownershipRoot, and moves the
    *   system to awaitingGovernance.
     * @param verse - the current verse; the provision of this param is required
     *  to avoid replay attacks.
     */
    function unavailableTXData(uint256 verse) external onlySuperUser
    {
        uint256 timeToFetchFromIPFS = IStorageGetters(_sto).verseInterval();
        address dummyStaker = address(0);
        _moveToGovernanceFromWrongTXsPublished(verse, timeToFetchFromIPFS, dummyStaker);
        _bypassCurrentVerse(verse);
    }

    /// @inheritdoc IUpdates
    function wrongTXDataRoot(uint256 verse) external
    {
        _moveToGovernanceFromWrongTXsPublished(verse, 0, msg.sender);
        _bypassCurrentVerse(verse);
    }

    /**
     * @notice Adds Dummy Ownership Root
     */
    function _addDummyOwnershipRoot(address staker, uint256 txSubmissionTime) private {
        IWriter(_writer).addOwnershipRoot(0, txSubmissionTime);
        IWriter(_writer).addChallenge(0, staker);
    }
    /**
     * @notice Implements transitions from awatiting ownershipRoot to Governance
     */
    function _moveToGovernanceFromWrongTXsPublished(
        uint256 verse,
        uint256 timeToFetchFromIPFS,
        address staker
    ) private {
        require(
            IInfo(_info).isReadyForOwnershipSubmission(),
            "Updates::_moveToGovernanceFromWrongTXsPublished: system not awaiting for ownership submission"
        );
        require(
            IStorageGetters(_sto).txRootsCurrentVerse() == verse,
            "Updates::_moveToGovernanceFromWrongTXsPublished: incorrect provided verse"
        );
        uint256 txSubmissionTime = IStorageGetters(_sto).txSubmissionTimeCurrent();
        require(
            block.timestamp > (txSubmissionTime + timeToFetchFromIPFS),
            "Updates::_moveToGovernanceFromWrongTXsPublished: not enough time passed to claim TXData issues"
        );
        // Before activating governance, first fake the second part of the ping-pong
        // with a submission of a null ownership root, right after the submission of NewTXs
        _addDummyOwnershipRoot(staker, txSubmissionTime+1);
        IWriter(_writer).activateGovernance();
        emit UnavailableTXData(verse);  
    }

    // @inheritdoc IUpdates
    function wrongUniverseRoot(uint256 universeIdx, uint256 verse) external {
        address stakers =  IStorageGetters(_sto).stakers();
        require(
            IStakers(stakers).isStaker(msg.sender),
            "only staker can report wrong universe root"
        );

        if (IInfo(_info).isReadyForOwnershipSubmission() || IInfo(_info).isReadyForChallenge()) {
            uint256 txRootCurrentVerse = IStorageGetters(_sto).txRootsCurrentVerse();
            _bypassCurrentVerse(txRootCurrentVerse);
        }

        _moveToGovernanceFromWrongUniverseRootPublished(universeIdx, verse);
    }

    /**
     * @notice Moves to governance when wrong universe root is published
     */
    function _moveToGovernanceFromWrongUniverseRootPublished(
        uint256 universeIdx,
        uint256 verse
    ) private {
        require(
            IStorageGetters(_sto).universeVerse(universeIdx) == verse,
            "Updates::_moveToGovernanceFromWrongUniverseRootPublished: incorrect provided verse"
        );

        require(
            IInfo(_info).isUniverseRootReadyForChallenge(universeIdx),
            "not ready for wrongUniverseRoot submission"
        );
        IWriter(_writer).activateGovernance();
        emit WrongUniverseRoot(universeIdx, verse);
    }

    /**
     * @notice Requests that universe roots of a given universe cannot be updated further.
     * @dev Requires that the universe is not already closed
     * @param universeIdx the idx of the Universe
     * @param validUntil the time until which the query will be valid
     * @param signature The signature of the universe owner
     */
    function requestUniverseClosure(
        uint256 universeIdx,
        uint256 validUntil,
        bytes calldata signature
    ) external onlyUniversesRelayer {
        // Check that the signature is from the universe owner
        bytes32 msgHash = prefixed(
            keccak256(abi.encode("RequestClosure", universeIdx, validUntil))
        );
        require(
            IStorageGetters(_sto).universeOwner(universeIdx) ==
                recoverAddrFromBytes(msgHash, signature),
            "requestUniverseClosure: signature not correct"
        );
        require(
            validUntil > block.timestamp,
            "requestUniverseClosure: request expired"
        );
        require(
            !IStorageGetters(_sto).universeIsClosed(universeIdx),
            "requestUniverseClosure: universe already closed"
        );
        IWriter(_writer).changeUniverseClosure(universeIdx, true, false);
        emit UniverseClosure(universeIdx, true, false);
    }

    /**
     * @notice Confirms that universe roots cannot be updated further.
     * @dev Requires a previous request to exist
     * @param universeIdx the idx of the Universe
     * @param validUntil the time until which the query will be valid
     * @param signature The signature of the universe owner
     */
    function confirmUniverseClosure(
        uint256 universeIdx,
        uint256 validUntil,
        bytes calldata signature
    ) external onlyUniversesRelayer {
        // Check that the signature is from the universe owner
        bytes32 msgHash = prefixed(
            keccak256(abi.encode("ConfirmClosure", universeIdx, validUntil))
        );
        require(
            IStorageGetters(_sto).universeOwner(universeIdx) ==
                recoverAddrFromBytes(msgHash, signature),
            "requestUniverseClosure: signature not correct"
        );
        require(
            validUntil > block.timestamp,
            "requestUniverseClosure: request expired"
        );
        require(
            !IStorageGetters(_sto).universeIsClosed(universeIdx),
            "requestUniverseClosure: universe already closed"
        );
        require(
            IStorageGetters(_sto).universeIsClosureRequested(universeIdx),
            "requestUniverseClosure: universe closure must be requested before confirming"
        );
        IWriter(_writer).changeUniverseClosure(universeIdx, true, true);
        emit UniverseClosure(universeIdx, true, true);
    }

    /**
     * @notice Removes initial request of universe closure. Cannot be used if already confirmed.
     * @param universeIdx the idx of the Universe
     * @param validUntil the time until which the query will be valid
     * @param signature The signature of the universe owner
     */
    function removeUniverseClosureRequest(
        uint256 universeIdx,
        uint256 validUntil,
        bytes calldata signature
    ) external onlyUniversesRelayer {
        // Check that the signature is from the universe owner
        bytes32 msgHash = prefixed(
            keccak256(
                abi.encode("RemoveClosureRequest", universeIdx, validUntil)
            )
        );
        require(
            IStorageGetters(_sto).universeOwner(universeIdx) ==
                recoverAddrFromBytes(msgHash, signature),
            "removeUniverseClosureRequest: signature not correct"
        );
        require(
            validUntil > block.timestamp,
            "removeUniverseClosureRequest: request expired"
        );
        require(
            !IStorageGetters(_sto).universeIsClosed(universeIdx),
            "removeUniverseClosureRequest: universe already closed"
        );
        IWriter(_writer).changeUniverseClosure(universeIdx, false, false);
        emit UniverseClosure(universeIdx, false, false);
    }

    /**
     * Main getters
     */

    /// @inheritdoc IUpdates
    function isReadyForOwnershipSubmission() public view returns (bool) {
        return IInfo(_info).isReadyForOwnershipSubmission();
    }

    /// @inheritdoc IUpdates
    function emitOwnershipIPFSAtVerse(uint256 verse, string calldata ipfsCid)
        external
        onlyTXRelayer
    {
        emit OwnershipIPFSAtVerse(verse, ipfsCid);
    }

    /// @inheritdoc IUpdates
    function computeLevelVerifiableOnChain(
        uint256 nTXs,
        uint256 nLeavesPerChallenge
    ) public pure returns (uint8 levelVeriableByBC) {
        levelVeriableByBC = 3;
        uint256 maxTXs = nLeavesPerChallenge;
        while (nTXs > maxTXs) {
            levelVeriableByBC++;
            maxTXs *= nLeavesPerChallenge;
        }
    }
}

File 2 of 17 : SerializeMerkleGet.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Deserialization of Merkle Tree parameters
 @author Freeverse.io, www.freeverse.io
*/

import "./SerializeBase.sol";

contract SerializeMerkleGet is SerializeBase {
    // Merkle Proof Getters (for transition proofs, merkle proofs in general)
    function MTPos(bytes memory serialized) public pure returns (uint256 pos) {
        assembly {
            pos := mload(add(serialized, 32))
        }
    }

    function MTLeaf(bytes memory serialized)
        public
        pure
        returns (bytes32 root)
    {
        assembly {
            root := mload(add(serialized, 64))
        } // 8 + 2 * 32
    }

    function MTProof(bytes memory serialized)
        public
        pure
        returns (bytes32[] memory proof)
    {
        // total length = 32 * 2 + 32 * nEntries
        uint32 nEntries = (uint32(serialized.length) - 64) / 32;
        require(
            serialized.length == 32 * 2 + 32 * nEntries,
            "incorrect serialized length"
        );
        return bytesToBytes32ArrayWithoutHeader(serialized, 64, nEntries);
    }
}

File 3 of 17 : SerializeBase.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Common tool for serilization/deserialization functions
 @author Freeverse.io, www.freeverse.io
*/

contract SerializeBase {
    // For all types of txs you always start with 1 byte for tx type:
    function txGetType(bytes memory serialized)
        public
        pure
        returns (uint8 txType)
    {
        assembly {
            txType := mload(add(serialized, 1))
        }
    }

    function bytesToBytes32ArrayWithoutHeader(
        bytes memory input,
        uint256 offset,
        uint32 nEntries
    ) public pure returns (bytes32[] memory) {
        bytes32[] memory output = new bytes32[](nEntries);

        for (uint32 p = 0; p < nEntries; p++) {
            offset += 32;
            bytes32 thisEntry;
            assembly {
                thisEntry := mload(add(input, offset))
            }
            output[p] = thisEntry;
        }
        return output;
    }
}

File 4 of 17 : Messages.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Pure library to recover address from signatures
*/

contract Messages {
    /**
     @notice retrieves the addr that signed a message
     @param msgHash the message digest
     @param sig the message signature
     @return the retrieved address
     */
    function recoverAddrFromBytes(bytes32 msgHash, bytes memory sig)
        public
        pure
        returns (address)
    {
        bytes32 r;
        bytes32 s;
        uint8 v;

        if (sig.length != 65) {
            return address(0x0);
        }

        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := and(mload(add(sig, 65)), 255)
        }

        if (v < 27) {
            v += 27;
        }

        if (v != 27 && v != 28) {
            return address(0);
        }
        return ecrecover(msgHash, v, r, s);
    }

    /**
     @notice retrieves the addr that signed a message
     @param msgHash the message digest
     @param v,r,s the (v,r,s) params of the signtature
     @return the retrieved address
     */
    function recoverAddr(
        bytes32 msgHash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public pure returns (address) {
        return ecrecover(msgHash, v, r, s);
    }

    /**
     @notice Returns the hash after prepending eth_sign prefix
     @param hash the hash before prepending
     @return the hash after prepending eth_sign prefix
     */
    function prefixed(bytes32 hash) public pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
            );
    }
}

File 5 of 17 : MerkleTreeBase.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Base functions for Standard Merkle Trees
*/

contract MerkleTreeBase {
    bytes32 constant NULL_BYTES32 = bytes32(0);

    function hash_node(bytes32 left, bytes32 right)
        public
        pure
        returns (bytes32 hash)
    {
        if ((right == NULL_BYTES32) && (left == NULL_BYTES32))
            return NULL_BYTES32;
        assembly {
            mstore(0x00, left)
            mstore(0x20, right)
            hash := keccak256(0x00, 0x40)
        }
        return hash;
    }

    function buildProof(
        uint256 leafPos,
        bytes32[] memory leaves,
        uint256 nLevels
    ) public pure returns (bytes32[] memory proof) {
        if (nLevels == 0) {
            require(
                leaves.length == 1,
                "buildProof: leaves length must be 0 if nLevels = 0"
            );
            require(
                leafPos == 0,
                "buildProof: leafPos must be 0 if there is only one leaf"
            );
            return proof; // returns the empty array []
        }
        uint256 nLeaves = 2**nLevels;
        require(
            leaves.length == nLeaves,
            "number of leaves is not = pow(2,nLevels)"
        );
        proof = new bytes32[](nLevels);
        // The 1st element is just its pair
        proof[0] = ((leafPos % 2) == 0)
            ? leaves[leafPos + 1]
            : leaves[leafPos - 1];
        // The rest requires computing all hashes
        for (uint8 level = 0; level < nLevels - 1; level++) {
            nLeaves /= 2;
            leafPos /= 2;
            for (uint256 pos = 0; pos < nLeaves; pos++) {
                leaves[pos] = hash_node(leaves[2 * pos], leaves[2 * pos + 1]);
            }
            proof[level + 1] = ((leafPos % 2) == 0)
                ? leaves[leafPos + 1]
                : leaves[leafPos - 1];
        }
    }

    /**
    * @dev 
        if nLevel = 0, there is one single leaf, corresponds to an empty proof
        if nLevels = 1, we need 1 element in the proof array
        if nLevels = 2, we need 2 elements...
            .
            ..   ..
        .. .. .. ..
        01 23 45 67
    */
    function MTVerify(
        bytes32 root,
        bytes32[] memory proof,
        bytes32 leafHash,
        uint256 leafPos
    ) public pure returns (bool) {
        for (uint32 pos = 0; pos < proof.length; pos++) {
            if ((leafPos % 2) == 0) {
                leafHash = hash_node(leafHash, proof[pos]);
            } else {
                leafHash = hash_node(proof[pos], leafHash);
            }
            leafPos /= 2;
        }
        // return false if leafPos was too large for given tree depth
        // (at level previous to root, leafPos had to be 0 or 1,
        // so at the end of last iteration, it must be 0)
        return (leafPos == 0) && (root == leafHash);
    }
}

File 6 of 17 : MerkleSerialized.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Merkle Tree Verify for serialized inputs
 @dev Unpacks serialized inputs and then calls Merkle Tree Verify
*/

import "../pure/Merkle.sol";
import "../pure/serialization/SerializeMerkleGet.sol";

contract MerkleSerialized is Merkle, SerializeMerkleGet {
    /**
    @dev
         MTData serializes the leaf, its position, and the proof that it belongs to a tree
         MTVerifySerialized returns true if such tree has root that coincides with the provided root.
    */
    function MTVerifySerialized(bytes32 root, bytes memory MTData)
        public
        pure
        returns (bool)
    {
        return MTVerify(root, MTProof(MTData), MTLeaf(MTData), MTPos(MTData));
    }
}

File 7 of 17 : Merkle.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Computation of Root in Standard Merkle Tree
 @author Freeverse.io, www.freeverse.io
 @dev Version that does not overwrite the input leaves
*/

import "../pure/MerkleTreeBase.sol";

contract Merkle is MerkleTreeBase {
    /**
    * @dev 
        If it is called with nLeaves != 2**nLevels, then it behaves as if zero-padded to 2**nLevels
        If it is called with nLeaves != 2**nLevels, then it behaves as if zero-padded to 2**nLevels
        Assumed convention:
        nLeaves = 1, nLevels = 0, there is one leaf, which coincides with the root
        nLeaves = 2, nLevels = 1, the root is the hash of both leaves
        nLeaves = 4, nLevels = 2, ...
    */
    function merkleRoot(bytes32[] memory leaves, uint256 nLevels)
        public
        pure
        returns (bytes32)
    {
        if (nLevels == 0) return leaves[0];
        uint256 nLeaves = 2**nLevels;
        require(
            nLeaves >= leaves.length,
            "merkleRoot: not enough levels given the number of leaves"
        );

        /**
        * @dev 
            instead of reusing the leaves array entries to store hashes leaves,
            create a half-as-long array (_leaves) for that purpose, to avoid modifying
            the input array. Solidity passes-by-reference when the function is in the same contract)
            and passes-by-value when calling a function in an external contract
        */
        nLeaves /= 2;
        bytes32[] memory _leaves = new bytes32[](nLeaves);

        // level = 0 uses the original leaves:
        uint256 nLeavesNonNull = leaves.length / 2;
        for (uint256 pos = 0; pos < nLeavesNonNull; pos++) {
            _leaves[pos] = hash_node(leaves[2 * pos], leaves[2 * pos + 1]);
        }

        if (leaves.length % 2 != 0) {
            _leaves[nLeavesNonNull] = hash_node(leaves[leaves.length - 1], NULL_BYTES32);
            nLeavesNonNull += 1;
        }

        // levels > 0 reuse the smaller _leaves array:
        for (uint8 level = 1; level < nLevels; level++) {
            nLeaves /= 2;
            nLeavesNonNull = (nLeavesNonNull % 2 == 0)
                ? (nLeavesNonNull / 2)
                : ((nLeavesNonNull / 2) + 1);
            if (nLeavesNonNull > nLeaves) nLeavesNonNull = nLeaves;

            for (uint256 pos = 0; pos < nLeavesNonNull; pos++) {
                _leaves[pos] = hash_node(
                    _leaves[2 * pos],
                    _leaves[2 * pos + 1]
                );
            }
            for (uint256 pos = nLeavesNonNull; pos < nLeaves; pos++) {
                _leaves[pos] = NULL_BYTES32;
            }
        }
        return _leaves[0];
    }
}

File 8 of 17 : IWriter.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract with write authorization to storage
 @author Freeverse.io, www.freeverse.io
*/

interface IWriter {
    /**
     * @notice Returns address of the license details for the contract code
     */
    function license() external view returns (string memory);

    /**
     * @notice Returns the address of the Storage contract that
     * this contract can write to
     */
    function _sto() external view returns (address);

    /**
     * @notice Returns the address of the Stakers contract that
     * this contract can communicate with
     */
    function _stakers() external view returns (address);

    /**
     * @notice Returns the address of the Updates contract that
     * this contract can communicate with
     */
    function _updates() external view returns (address);

    /**
     * @notice Returns the address of the Challenges contract that
     * this contract can communicate with
     */
    function _challenges() external view returns (address);

    // Functions that write to the Storage Contract

    /**
     * @notice Adds a new root to a Universe
     * @param universeIdx The idx of the universe
     * @param root The root to be added
     * @param timestamp The timestamp to be associated
     * @return verse The verse at which the universe is after the addition
     */
    function addUniverseRoot(
        uint256 universeIdx,
        bytes32 root,
        uint256 timestamp
    ) external returns (uint256 verse);

    /**
     * @notice Adds a new TX root
     * @dev TXs are added in batches. When adding a new batch, the ownership root settled in the previous verse
     * is settled, by copying from the challenge struct to the last ownership entry.
     * @param txRoot The nex TX root to be added
     * @param timestamp The timestamp to be associated
     * @param nTXs The number of TXs included in the batch
     * @param actualLevel The level at which the last challenge ended at
     * @param levelVeriableByBC The level at which a Challenge can be verified by the blockchain contract
     * @return txVerse The length of the TX roots array after the addition
     */
    function addTXRoot(
        bytes32 txRoot,
        uint256 timestamp,
        uint256 nTXs,
        uint8 actualLevel,
        uint8 levelVeriableByBC
    ) external returns (uint256 txVerse);

    /**
     * @notice Adds a new Ownership root
     * @dev A new ownership root, ready for challenge is received.
     * Registers timestamp of reception, creates challenge and it
     * either appends to _ownerships, or rewrites last entry, depending on
     * whether it corresponds to a new verse, or it results from a challenge
     * to the current verse.
     * The latter can happen when the challenge game moved tacitly to level 0.
     * @param ownershipRoot The new ownership root to be added
     * @param timestamp The timestamp associated with the root added
     * @return ownVerse The length of the ownership array after the addition
     */
    function addOwnershipRoot(bytes32 ownershipRoot, uint256 timestamp)
        external
        returns (uint256 ownVerse);

    /**
     * @notice Pushes a challenge to the Challenges array
     * @param ownershipRoot The new proposed ownership root
     * @param transitionsRoot The transitions root provided by the challenger
     * @param rootAtEdge The edge-root stored at the provided challenge level
     * @param pos The position stored at the provided challenge level
     */
    function pushChallenge(
        bytes32 ownershipRoot,
        bytes32 transitionsRoot,
        bytes32 rootAtEdge,
        uint256 pos
    ) external;

    /**
     * @notice Sets the timestamp associated to the last ownership root received
     * @param timestamp The new time
     */
    function setLastOwnershipSubmissiontime(uint256 timestamp) external;

    /**
     * @notice Pops the last entries in the Challenge array as many times
     * as required to set its length to actualLevel
     */
    function popChallengeDataToLevel(uint8 actualLevel) external;

    /**
     * @notice Changes the data associated with the closure of a universe
     */
    function changeUniverseClosure(
        uint256 universeIdx,
        bool closureRequested,
        bool closureConfirmed
    ) external;

    /**
     * @dev Functions that write to Stakers conttact
     */

    /**
     * @notice Finalizes the currently opened challenge
     */
    function finalize() external;

    /**
     * @notice Adds a new challenge
     */
    function addChallenge(uint8 level, address staker) external;

    /**
     * @notice Resolves the last entries of a Challenge so as to
     * leave its final level to equal the provided level
     */
    function resolveToLevel(uint8 level) external;

    /**
     * @notice Pops updaters from a Challenge so as to
     * leave its final level to equal the provided level
     */
    function rewindToLevel(uint8 level) external;

    /**
     * @notice Rewrites the challenge struct created on reception
     *  of a first submitNewOwnershipRoot, so that it contains
     *  the previous verse's settled ownership root.   
     * @param ownershipRootPrevVerse The ownership root from the previous verse
     */
    function setProposedOwnershipToPrevVerse(bytes32 ownershipRootPrevVerse) external;

    /**
     * @notice Stores the input verse with a 'bypassed' mark in the storage contract 
     * @param verse The verse to be stored as 'bypassed'
     */
    function storeBypassedVerse(uint256 verse) external;

    /**
     * @notice Stores the input universe verse with a 'bypassed' mark in the storage contract
     * @param universeIdx universe index
     * @param verse The verse to be stored as 'bypassed'
     */
    function storeBypassedUniverseVerse(
        uint256 universeIdx,
        uint256 verse
    ) external;

    /**
     * @notice Sets to true the value of awaitingGovernance in the storage contract
     */
    function activateGovernance() external;

    /**
     * @notice Sets to false the value of awaitingGovernance in the storage contract
     */
    function deactivateGovernance() external;

    /**
     * @notice remove the last universe root from storage contract and returns current verse
     * @param universeIdx index of the universe
     * @return verse current verse after removal
     */
    function popUniverseRoot(
        uint256 universeIdx
    ) external returns (uint256 verse);
}

File 9 of 17 : IUpdates.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract that manages Updates of Multiverse properties and Ownership
 @author Freeverse.io, www.freeverse.io
*/

interface IUpdates {
    event NewUniverseRoot(
        uint256 indexed universeIdx,
        bytes32 indexed newRoot,
        uint256 indexed verse,
        string ipfsCid
    );
    event UniverseClosure(uint256 universeIdx, bool requested, bool confirmed);
    event NewTXsRoot(
        bytes32 indexed newRoot,
        uint256 nTXs,
        uint8 levelsPerChallenge,
        uint256 indexed verse,
        string ipfsCid
    );
    event NewOwnershipRoot(bytes32 indexed newRoot, uint256 indexed verse);
    event OwnershipIPFSAtVerse(uint256 indexed verse, string ipfsCid);
    event OwnershipTxFormatVersion(uint32 version);
    event OwnershipRootMismatch(uint256 indexed verse, bytes32 newProposedRoot);
    event BypassVerse(uint256 indexed verse);
    event BypassUniverseVerse(uint256 universeIdx, uint256 indexed verse);
    event UnavailableTXData(uint256 indexed verse);
    event WrongUniverseRoot(uint256 universeIdx, uint256 verse);

    /**
     * @notice Returns address of the license details for the contract code
     */
    function license() external view returns (string memory);

    /**
     * @notice Returns the address of the Storage contract that
     * this contract can communicate with
     */
    function _sto() external view returns (address);

    /**
     * @notice Returns the address of the Writer contract that
     * this contract can communicate with
     */
    function _writer() external view returns (address);

    /**
     * @notice Returns the address of the Info contract that
     * this contract can communicate with
     */
    function _info() external view returns (address);

    /**
     * @notice Returns the version number of the expected format
     * of ownership TXs     
     */
    function OWNERSHIP_TXFORMAT_VERSION() external returns (uint32);

    /**
     * @notice Submission of new Ownership state, open to challenge process until settling.
     * @dev Only stakers can submit, otherwise addChallenge would fail
     * The specified verse refers to the current verse opened by the last TXs submission
     * @param verse The tx verse of the processed TX Batch, leading to the new ownershipRoot
     * @param ownershipRoot The new ownership root
     * @param txFormatVersion The version of the txFormat used
     */
    function submitNewOwnershipRoot(uint256 verse, bytes32 ownershipRoot, uint32 txFormatVersion)
        external;

    /**
     * @notice After reception of a NewTXs transaction, the TX data can be fetched from
     *  IPFS, but its root does not coincide with the submitted one.
     * @dev Requires that the system is in awaiting ownershipRoot state, and moves the
     *   system to awaitingGovernance. Needs to be called by a staker.
     * @param verse - the current verse; the provision of this param is required
     *  to avoid replay attacks.
     */
    function wrongTXDataRoot(uint256 verse) external;

    /**
     * @notice Used to report universe root mismatch as a result of applying the universe transactions of the current verse
     * @dev moves the system to governance state
     * @param universeIdx universe index
     * @param verse universe verse that is challenged
     */
    function wrongUniverseRoot(uint256 universeIdx, uint256 verse) external;

    /**
     * @notice Returns true if the system is ready to accept a new ownership root
     * @dev When a TXs batch is submitted, a new Ownership state can be submitted.
     * @return Returns true if the system is ready to accept a new ownership root
     */
    function isReadyForOwnershipSubmission() external view returns (bool);

    /**
     * @notice Function to submit entire snapshots of the ownership state and inform via emission of event
     * @param verse The TX verse that the event refers to
     * @param ipfsCid The IPFS address of the data describing the event
     */
    function emitOwnershipIPFSAtVerse(uint256 verse, string calldata ipfsCid)
        external;

    /**
     * @notice Computes the level at which a challenge can be resolved by the blockchain contract
     * @dev Example:
     *  level 0: nothing has been submitted
     *  level 1: just submitted successfully: submitNewOwnershipRoot(bytes32 ownershipRoot, bytes32 transitionsRoot)
     *  level 2: either verifiable, or just submitted successfully: challenge( N roots)...
     * Formula nTXsMax = nLeavesPerChallenge^(levelBC-3) * (nLeavesPerChallenge - 1);
     * @param nTXs the number of TXs in the TX batch
     * @param nLeavesPerChallenge the number of leaves that each challenge level contains
     */
    function computeLevelVerifiableOnChain(
        uint256 nTXs,
        uint256 nLeavesPerChallenge
    ) external pure returns (uint8 levelVeriableByBC);
}

File 10 of 17 : IStorageGetters.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to the main storage getters
 @author Freeverse.io, www.freeverse.io
*/

interface IStorageGetters {
    /**
     * @notice Returns address of the license details for the contract code
     */
    function license() external view returns (string memory);

    // UNIVERSE GETTERS

    /**
     * @notice Returns the owner of a universe
     * @param universeIdx The idx of the universe
     * @return The address of the owner
     */
    function universeOwner(uint256 universeIdx) external view returns (address);

    /**
     * @notice Returns the name of a universe
     * @param universeIdx The idx of the universe
     * @return The name of the universe
     */
    function universeName(uint256 universeIdx)
        external
        view
        returns (string memory);

    /**
     * @notice Returns whether owner of a universe authorizes the default relayer
     * @param universeIdx The idx of the universe
     * @return Returns true if owner of a universe authorizes the default relayer
     */
    function universeAuthorizesRelay(uint256 universeIdx)
        external
        view
        returns (bool);

    /**
     * @notice Returns the current verse at which a universe is
     * @param universeIdx The idx of the universe
     * @return The verse
     */
    function universeVerse(uint256 universeIdx) external view returns (uint256);

    /**
     * @notice Returns the root of a universe at the provided verse
     * @param universeIdx The idx of the universe
     * @param verse The verse queried
     * @return The root of the universe at the provided verse
     */
    function universeRootAtVerse(uint256 universeIdx, uint256 verse)
        external
        view
        returns (bytes32);

    /**
     * @notice Returns current root of a universe
     * @param universeIdx The idx of the universe
     * @return The root of the universe at the current verse
     */
    function universeRootCurrent(uint256 universeIdx)
        external
        view
        returns (bytes32);

    /**
     * @notice Returns the number of universes created
     * @return The number of universes created
     */
    function nUniverses() external view returns (uint256);

    /**
     * @notice Returns the submission time of a universe root at the
     * provided verse
     * @param universeIdx The idx of the universe
     * @param verse The verse queried
     * @return The submission time
     */
    function universeRootSubmissionTimeAtVerse(
        uint256 universeIdx,
        uint256 verse
    ) external view returns (uint256);

    /**
     * @notice Returns the submission time of the current universe root
     * @param universeIdx The idx of the universe
     * @return The submission time
     */
    function universeRootSubmissionTimeCurrent(uint256 universeIdx)
        external
        view
        returns (uint256);

    /**
     * @notice Returns true if the universe if closed
     * @param universeIdx The idx of the universe
     * @return Returns true if it is closed
     */
    function universeIsClosed(uint256 universeIdx) external view returns (bool);

    /**
     * @notice Returns true if the universe has its closure requested
     * @param universeIdx The idx of the universe
     * @return Returns true if it has its closure requested
     */
    function universeIsClosureRequested(uint256 universeIdx)
        external
        view
        returns (bool);

    // OWNERSHIP GETTERS

    /**
     * @notice Returns the amount of time allowed for challenging
     * an ownership root that is currently set as default for next verses
     * @return the amount of time allowed for challenging
     */
    function challengeWindowNextVerses() external view returns (uint256);

    /**
     * @notice Returns the number of levels contained in each challenge
     * set as default for next verses
     * @return the number of levels contained in each challenge
     */
    function nLevelsPerChallengeNextVerses() external view returns (uint8);

    /**
     * @notice Returns the maximum time since the production of the last
     * verse beyond which assets can be exported without new verses being produced
     * @return the maximum time
     */
    function maxTimeWithoutVerseProduction() external view returns (uint256);

    /**
     * @notice Returns information about possible export requests about the provided asset
     * @param assetId The id of the asset
     * @return owner The owner that requested the asset export
     * @return requestVerse The TX verse at which the export request was received
     * @return completedVerse The TX verse at which the export process was completed (0 if not completed)
     */
    function exportRequestInfo(uint256 assetId)
        external
        view
        returns (
            address owner,
            uint256 requestVerse,
            uint256 completedVerse
        );

    /**
     * @notice Returns the owner that requested the asset export
     * @param assetId The id of the asset
     * @return owner The owner that requested the asset export
     */
    function exportOwner(uint256 assetId) external view returns (address owner);

    /**
     * @notice Returns the TX verse at which the export request was received
     * @param assetId The id of the asset
     * @return requestVerse The TX verse at which the export request was received
     */
    function exportRequestVerse(uint256 assetId)
        external
        view
        returns (uint256 requestVerse);

    /**
     * @notice Returns the TX verse at which the export process was completed (0 if not completed)
     * @param assetId The id of the asset
     * @return completedVerse The TX verse at which the export process was completed (0 if not completed)
     */
    function exportCompletedVerse(uint256 assetId)
        external
        view
        returns (uint256 completedVerse);

    /**
     * @notice Returns the length of the ownership root array
     * @return the length of the ownership root array
     */
    function ownershipCurrentVerse() external view returns (uint256);

    /**
     * @notice Returns the length of the TXs root array
     * @return the length of the TXs root array
     */
    function txRootsCurrentVerse() external view returns (uint256);

    /**
     * @notice Returns the reference verse used in the computation of
     * the time planned for the submission of a TX batch for a given verse
     * @return The reference verse
     */
    function referenceVerse() external view returns (uint256);

    /**
     * @notice Returns the timestamp at which the reference verse took
     * place used, in the computation of the time planned for
     * the submission of a TX batch for a given verse
     * @return The timestamp at which the reference verse took place
     */
    function referenceTime() external view returns (uint256);

    /**
     * @notice Returns the seconds between txVerses between TX batch
     * submissions, used in the computation of the time planned for
     * each submission
     * @return The seconds between txVerses
     */
    function verseInterval() external view returns (uint256);

    /**
     * @notice Returns the ownership root at the provided verse
     * @param verse The verse queried
     * @return The ownership root at the provided verse
     */
    function ownershipRootAtVerse(uint256 verse)
        external
        view
        returns (bytes32);

    /**
     * @notice Returns the TX root at the provided verse
     * @param verse The verse queried
     * @return The TX root at the provided verse
     */
    function txRootAtVerse(uint256 verse) external view returns (bytes32);

    /**
     * @notice Returns the number of levels contained in each challenge
     * at the provided verse
     * @param verse The verse queried
     * @return The TX root at the provided verse
     */
    function nLevelsPerChallengeAtVerse(uint256 verse)
        external
        view
        returns (uint8);

    /**
     * @notice Returns the challenge level verifiable on chain
     * at the provided verse
     * @param verse The verse queried
     * @return The level verifiable on chain
     */
    function levelVerifiableOnChainAtVerse(uint256 verse)
        external
        view
        returns (uint8);

    /**
     * @notice Returns the number of TXs included in the batch at
     * the provided verse
     * @param verse The verse queried
     * @return The number of TXs included in the batch
     */
    function nTXsAtVerse(uint256 verse) external view returns (uint256);

    /**
     * @notice Returns the amount of time allowed for challenging
     * an ownership root at the provided verse
     * @param verse The verse queried
     * @return the amount of time allowed for challenging
     */
    function challengeWindowAtVerse(uint256 verse)
        external
        view
        returns (uint256);

    /**
     * @notice Returns the submission time of the TX batch
     * at the provided verse
     * @param verse The verse queried
     * @return the submission time of the TX batch
     */
    function txSubmissionTimeAtVerse(uint256 verse)
        external
        view
        returns (uint256);

    /**
     * @notice Returns the submission time of the Ownership root
     * at the provided verse
     * @param verse The verse queried
     * @return the submission time of the Ownership root
     */
    function ownershipSubmissionTimeAtVerse(uint256 verse)
        external
        view
        returns (uint256);

    /**
     * @notice Returns the last entry of the ownership root array
     * @return the last entry of the ownership root array
     */
    function ownershipRootCurrent() external view returns (bytes32);

    /**
     * @notice Returns the last entry of the TXs root array
     * @return the last entry of the TXs root array
     */
    function txRootCurrent() external view returns (bytes32);

    /**
     * @notice Returns the number of levels contained in each challenge
     * in the current verse
     * @return the number of levels contained in each challenge
     */
    function nLevelsPerChallengeCurrent() external view returns (uint8);

    /**
     * @notice Returns the challenge level verifiable on chain
     * in the current verse
     * @return The level verifiable on chain
     */
    function levelVerifiableOnChainCurrent() external view returns (uint8);

    /**
     * @notice Returns the number of TXs included in the batch
     * in the current verse
     * @return The number of TXs included in the batch
     */
    function nTXsCurrent() external view returns (uint256);

    /**
     * @notice Returns the amount of time allowed for challenging
     * an ownership root in the current verse
     * @return the amount of time allowed for challenging
     */
    function challengeWindowCurrent() external view returns (uint256);

    /**
     * @notice Returns the submission time of the TX batch
     * in the current verse
     * @return the submission time of the TX batch
     */
    function txSubmissionTimeCurrent() external view returns (uint256);

    /**
     * @notice Returns the submission time of the Ownership root
     * in the current verse
     * @return the submission time of the Ownership root
     */
    function ownershipSubmissionTimeCurrent() external view returns (uint256);

    // CHALLENGES GETTERS

    /**
     * @notice Returns the ownership root stored at the provided challenge level
     * @param level The queried challenge level
     * @return the stored root
     */
    function challengesOwnershipRoot(uint8 level)
        external
        view
        returns (bytes32);

    /**
     * @notice Returns the transitions root stored at the provided challenge level
     * @param level The queried challenge level
     * @return the stored root
     */
    function challengesTransitionsRoot(uint8 level)
        external
        view
        returns (bytes32);

    /**
     * @notice Returns the edge-root stored at the provided challenge level
     * @param level The queried challenge level
     * @return the stored root
     */
    function challengesRootAtEdge(uint8 level) external view returns (bytes32);

    /**
     * @notice Returns the position stored at the provided challenge level
     * @param level The queried challenge level
     * @return the position
     */
    function challengesPos(uint8 level) external view returns (uint256);

    /**
     * @notice Returns the level stored in the current challenge process
     * @return the level
     */
    function challengesLevel() external view returns (uint8);

    /**
     * @notice Returns true if all positions stored in the current
     * challenge process are zero
     * @return Returns true if all positions are zero
     */
    function areAllChallengePosZero() external view returns (bool);

    /**
     * @notice Returns number of leaves contained in each challenge
     * in the current verse
     * @return Returns true if all positions are zero
     */
    function nLeavesPerChallengeCurrent() external view returns (uint256);

    /**
     * @notice Returns the position of the leaf at the bottom level
     * of the current challenge process
     * @return bottomLevelLeafPos The position of the leaf
     */
    function computeBottomLevelLeafPos(uint256)
        external
        view
        returns (uint256 bottomLevelLeafPos);

    // ROLES GETTERS

    /**
     * @notice Returns the address with company authorization
     */
    function company() external view returns (address);

    /**
     * @notice Returns the address proposed for company authorization
     */
    function proposedCompany() external view returns (address);

    /**
     * @notice Returns the address with super user authorization
     */
    function superUser() external view returns (address);

    /**
     * @notice Returns the address with universe-roots relayer authorization
     */
    function universesRelayer() external view returns (address);

    /**
     * @notice Returns the address with TX Batch relayer authorization
     */
    function txRelayer() external view returns (address);

    /**
     * @notice Returns the address of the Stakers contract
     */
    function stakers() external view returns (address);

    /**
     * @notice Returns the address of the Writer contract
     */
    function writer() external view returns (address);

    /**
     * @notice Returns the address of the Directory contract
     */
    function directory() external view returns (address);

    /**
     * @notice Returns the address of the NFT contract where
     * assets are minted when exported
     */
    function externalNFTContract() external view returns (address);

    /**
     * @notice Returns the address of the Assets Exporter contract
     */
    function assetExporter() external view returns (address);

    // CLAIMS GETTERS

    /**
     * @notice Returns the (verse, value) pair of the provided key
     * in the provided claim
     * @param claimIdx The Idx that identifies claim
     * @param key The key queried the claim
     * @return verse The verse at which the key was set
     * @return value The value that corresponds to the key
     */
    function claim(uint256 claimIdx, uint256 key)
        external
        view
        returns (uint256 verse, string memory value);

    /**
     * @notice Returns the number of Claims created
     * @return the number of Claims created
     */
    function nClaims() external view returns (uint256);
}

File 11 of 17 : IStorageExtension.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract for querying and using storage extensions 
 @author Freeverse.io, www.freeverse.io
*/

import "../interfaces/IBlackholeId.sol";
import "../interfaces/IGovernance.sol";
import "../interfaces/IBypassedOwnershipVerses.sol";

interface IStorageExtension is IBlackholeId, IGovernance, IBypassedOwnershipVerses {

    /**
     * @notice Reverts unless the Storage contract stores the expected
     *  claims, with the expected allowed values
     */
    function assertValidStorageExtension() external view;
}

File 12 of 17 : IStakers.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract that Manages Stakers and their deposits. 
 @author Freeverse.io, www.freeverse.io
*/

interface IStakers {
    event PotBalanceChange(uint256 newBalance);
    event RewardsExecuted();
    event AddedTrustedParty(address indexed party);
    event RemovedTrustedParty(address indexed party);
    event NewEnrol(address indexed staker);
    event NewUnenrol(address indexed staker);
    event SlashedBy(address indexed slashedStaker, address indexed goodStaker);
    event AddedRewardToUpdater(address indexed staker);
    event FinalizedLogicRound();
    event NewLevel(uint16 indexed level);

    /**
     * @notice Returns address of the license details for the contract code
     */
    function license() external view returns (string memory);

    /**
     * @notice Returns address of the storage contract that
     * this contract is attached to.
     */
    function sto() external view returns (address);

    /**
     * @notice Returns the factor required to convert the smallest unit
     *  of the currency in the blockchain of deploy to Wei.
     *  Examples:
     *      for Ethereum, Polygon, XDAI, should return 1
     *      for Hedera, which uses tinybars, should return 1e10
     * @return the conversion factor to Wei
     */
    function TO_WEI() external view returns (uint256);

    /**
     * @notice Returns true if the provided address is registered as staker.
     * @return whether the provided address is a staker
     */
    function isStaker(address) external view returns (bool);

    /**
     * @notice Returns true if the provided address is has been slashed.
     * @return whether the provided address has been slashed
     */
    function isSlashed(address) external view returns (bool);

    /**
     * @notice Returns true if the provided address is registered as trusted party.
     * @return whether the provided address is a trusted party
     */
    function isTrustedParty(address) external view returns (bool);

    /**
     * @notice Returns the amount staked by the provided address.
     * @return the amount staked by the provided address.
     */
    function stakes(address) external view returns (uint256);

    /**
     * @notice Returns the amount available for withdrawal
     * by the the provided address.
     * @return the amount available for withdrawal
     */
    function pendingWithdrawals(address) external view returns (uint256);

    /**
     * @notice Returns the number of updates performed
     * by the the provided address since the last event of
     * reward execution
     * @return the number of updates performed
     */
    function nUpdates(address) external view returns (uint256);

    /**
     * @notice Returns the number of currently registered trusted parties
     * @return the number of currently registered trusted parties
     */
    function nTrustedParties() external view returns (uint256);

    /**
     * @notice Returns the number of currently registered stakers
     * @return the number of currently registered stakers
     */
    function nStakers() external view returns (uint256);

    /**
     * @notice Returns the idx-th address that was ever registered.
     *  This array is never decreasing. Some addresses may, or may not,
     *  be trustedParties or stakers at present time.
     *  Use the isTrustedParty and isStaker methods to filter.
     * @param idx The index in the array
     * @return the address at the idx provided
     */
    function registeredParty(uint256 idx) external view returns (address);

    /**
     * @notice Returns the idx-th trustedParty address
     * @param idx The position of the queried trustedParty
     * @return the idx-th trustedParty address
     */
    function trustedParty(uint256 idx) external view returns (address);

    /**
     * @notice Returns the idx-th staker address
     * @param idx The position of the queried staker
     * @return the idx-th staker address
     */
    function staker(uint256 idx) external view returns (address);


    /**
     * @notice Returns the stake amount required to join as staker
     * @return the stake amount required to join as staker interpreted in WEI
     */
    function requiredStake() external view returns (uint256);

    /**
     * @notice Returns the amount available in the pot
     * @return the amount available in the pot
     */
    function potBalance() external view returns (uint256);

    /**
     * @notice Returns total number of updates performed since
     * the last event of reward execution
     * @return the total number of updates performed
     */
    function totalNumUpdates() external view returns (uint256);

    /**
     * @notice Returns the address at the provided idx of the array of
     * stakers to be rewarded
     * @param idx The index in the array
     * @return the address of the staker to be rewarded at the idx provided
     */
    function toBeRewarded(uint256 idx) external view returns (address);

    /**
     * @notice Returns the address of the updater at the idx provided
     * @param idx The index in the array
     * @return the address of the updater at the idx provided
     */
    function updaters(uint256 idx) external view returns (address);

    /**
     * @notice Transfers pendingWithdrawals to the calling staker;
     * @dev the stake remains until unenrol is called
     */
    function withdraw() external;

    /**
     * @notice Reverts if the address does not fulfil the conditions
     * required to become a trusted party
     */
    function assertGoodCandidate(address _addr) external view;

    /**
     * @notice Registers a new staker
     * @dev Must be called by the candidate
     */
    function enrol() external payable;

    /**
     * @notice Unregisters a staker and transfers all earnings
     * @dev Must be called by the corresponding staker
     */
    function unEnroll() external;

    /**
     * @notice Update to a new level
     * @dev This function will also resolve previous updates when
     * level is below current or level has reached the end
     * Requiring that _staker is not slashed is already covered by not being part of stakers,
     * because slashing removes address from stakers
     * @param _level to which update
     * @param _staker address of the staker that reports this update
     */
    function addChallenge(uint16 _level, address _staker) external;

    /**
     * @notice Resolves a challenge at the provided level
     * @param _level at which we will end up, due to a level proven right,
     * and previous one proven wrong, possibly a few times.
     */
    function resolveToLevel(uint16 _level) external;

    /**
     * @notice Rewinds a challenge process to a previous level
     * @param _level at which we will end up, due to a challenge to a previously-challenged level.
     */
    function rewindToLevel(uint16 _level) external;

    /**
     * @notice Finalize current challenge process, get ready for next one.
     * @dev Current state will be resolved at this point.
     * If called from level 1, then staker is rewarded.
     * When called from any other level, means that every
     * other staker told the truth but the one in between lied.
     */
    function finalize() external;

    /**
     * @notice Adds funds to pot to be shared by stakers who update
     * @dev Any address can add funds
     */
    function addRewardToPot() external payable;

    /**
     * @notice Returns true if the provided address has already
     * performed an update in the current challenge
     * @return whether the provided address has already performed an update
     */
    function alreadyDidUpdate(address _address) external view returns (bool);

    /**
     * @notice Returns the level at which the challenge is
     * @return the level at which the challenge is
     */
    function level() external view returns (uint16);
}

File 13 of 17 : IInfo.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract with info/view functions
 @author Freeverse.io, www.freeverse.io
*/

import "../interfaces/IChallengeLibStatus.sol";
import "../interfaces/IStorageExtension.sol";

interface IInfo is IChallengeLibStatus, IStorageExtension {

    /**
     * @notice The enum that describes the possible states of the L2 -> L1 ownership sync flow
     */
    enum OwnershipState { AWAIT_TXS, AWAIT_OWNERSHIP, AWAIT_CHALLENGE, AWAIT_VERSE_TICK, AWAIT_GOVERNANCE }

    /**
     * @notice Returns address of the license details for the contract code
     */
    function license() external view returns (string memory);

    /**
     * @notice Returns true only if the input owner owns the asset AND the asset has the provided props
     * @dev Proofs need to be provided. They are verified against current Ownerhsip and Universe roots.
     * @param assetId The id of the asset
     * @param owner The address of the asset owner
     * @param marketData The market data of the asset
     * @param assetCID The CID of the asset
     * @param ownershipProof The proof that the asset belongs to the current Ownership tree
     * @param propsProof The proof that the asset properties belong to the current Universe tree
     * @return whether the proofs are valid or not
     */
    function isCurrentOwnerOfAssetWithProps(
        uint256 assetId,
        address owner,
        bytes memory marketData,
        string memory assetCID,
        bytes memory ownershipProof,
        bytes memory propsProof
    ) external view returns (bool);

    /**
     * @notice Returns true only if the input owner owns the asset
     * @dev Proof needs to be provided. They are verified against current Ownership root
     * - if marketDataNeverTraded(marketData) == true (asset has never been included in the ownership tree)
     *   - it first verifies that it's not in the tree (the leafHash is bytes(0x0))
     *   - it then verifies that "owner" is the default owner
     * - if marketDataNeverTraded(marketData) == false (asset must be included in the ownership tree)
     *   - it only verifies owner == current owner stored in the ownership tree
     * Once an asset is traded once, marketDataNeverTraded remains false forever.
     * If asset has been exported, this function returns false; ownership needs to be queried in the external ERC721 contract.
     * @param assetId The id of the asset
     * @param owner The address of the asset owner
     * @param marketData The market data of the asset
     * @param proof The proof that the asset belongs to the current Ownership tree
     * @return whether the proof is valid or not
     */
    function isCurrentOwner(
        uint256 assetId,
        address owner,
        bytes memory marketData,
        bytes memory proof
    ) external view returns (bool);

    /**
     * @notice Returns true only if the input owner owned the asset at provided verse
     * @dev Identical to isCurrentOwner, but uses the Ownership root at provided verse
     * @param verse The ownership verse at which the query refers
     * @param assetId The id of the asset
     * @param owner The address of the asset owner
     * @param marketData The market data of the asset
     * @param proof The proof that the asset belonged to the Ownership tree at provided verse
     * @return whether the proof is valid or not
     */
    function wasOwnerAtVerse(
        uint256 verse,
        uint256 assetId,
        address owner,
        bytes memory marketData,
        bytes memory proof
    ) external view returns (bool);

    /**
     * @notice Serialized-inputs version of isCurrentOwner
     * @dev Unpacks inputs and calls isCurrentOwner
     * @param data The serialized ownership data
     * @return whether the proof contained in data is valid or not
     */
    function isCurrentOwnerSerialized(bytes memory data)
        external
        view
        returns (bool);

    /**
     * @notice Serialized-inputs version of wasOwnerAtVerse
     * @dev Unpacks inputs and calls wasOwnerAtVerse
     * @param verse The ownership verse at which the query refers
     * @param data The serialized ownership data
     * @return whether the proof contained in data is valid or not
     */
    function wasOwnerAtVerseSerialized(uint256 verse, bytes memory data)
        external
        view
        returns (bool);

    /**
     * @notice Returns true only if asset currently has the provided props
     * @dev Proof needs to be provided. They are verified against current Universe root
     * @param assetId The id of the asset
     * @param assetCID The CID of the asset
     * @param proof The proof that the asset belongs to the current Universe tree
     * @return whether the proof is valid or not
     */
    function isCurrentAssetProps(
        uint256 assetId,
        string memory assetCID,
        bytes memory proof
    ) external view returns (bool);

    /**
     * @notice Returns true only if the asset had the provided props at the provided verse
     * @dev Identical to isCurrentAssetProps, but uses the Universe root at the provided verse
     * @param assetId The id of the asset
     * @param verse The universe verse at which the query refers
     * @param assetCID The CID of the asset
     * @param proof The proof that the asset properties belonged to the
     * Universe tree at provided verse
     * @return whether the proof is valid or not
     */
    function wasAssetPropsAtVerse(
        uint256 assetId,
        uint256 verse,
        string memory assetCID,
        bytes memory proof
    ) external view returns (bool);

    /**
     * @notice Returns the last Ownership root that is fully settled (there could be one still in challenge process)
     * @dev There are 3 phases to consider.
     * 1. When submitTX just arrived, we just need to return the last stored ownership root
     * 2. When submitOwn just arrived, a temp root is added, so we return the last-to-last stored ownership root
     * 3. When the challenge period is over we return the settled root, which is in the challenge struct.
     * @return the current settled ownership root
     */
    function currentSettledOwnershipRoot() external view returns (bytes32);

    /**
     * @notice Returns the last settled ownership verse number
     * @return the settled ownership verse
     */
    function currentSettledOwnershipVerse() external view returns (uint256);

    /**
     * @notice Computes data about whether the system is in the phase that goes between
     * the finishing of the challenge period, and the arrival
     * of a new submission of a TX Batch
     * @return isChallengeOver Whether the system is in the phase between the settlement of
     * the last ownership root, and the submission of a new TX Batch
     * @return actualLevel The level at which the last challenge process is, accounting for
     * implicit time-driven changes
     * @return txVerse The current txVerse
     */
    function isInChallengePeriodFinishedPhase()
        external
        view
        returns (
            bool isChallengeOver,
            uint8 actualLevel,
            uint256 txVerse
        );

    /**
     * @notice Returns the current state of the ownership synchronization state machine
     * @return the current ownership state
     */
    function ownershipState() external view returns(OwnershipState);

    /**
     * @notice Computes data about whether the system is ready to accept
     * the submission of a new TX batch
     * @return isReady Whether the system is ready to accept a new TX batch submission
     * @return actualLevel The level at which the last challenge process is, accounting for
     * implicit time-driven changes
     */
    function isReadyForTXSubmission()
        external
        view
        returns (bool isReady, uint8 actualLevel);

    /**
     * @notice Returns the time planned for the submission of a TX batch for a given verse
     * @param verse The TX verse queried
     * @param referenceVerse The reference verse used in the computation
     * @param referenceTime The timestamp at which the reference verse took place
     * @param verseInterval The seconds between txVerses
     * @return the time planned for the submission of a TX batch for a given verse
     */
    function plannedTime(
        uint256 verse,
        uint256 referenceVerse,
        uint256 referenceTime,
        uint256 verseInterval
    ) external pure returns (uint256);

    /**
     * @notice Returns true if the system is ready to accept a new ownership root
     * @dev When a TXs batch is submitted, a new Ownership state can be submitted.
     * @return Returns true if the system is ready to accept a new ownership root
     */
    function isReadyForOwnershipSubmission() external view returns (bool);

    /**
     * @notice Returns true if the contract is ready to accept a new universe root submission
     * @param universeIdx universe index
     * @return isReady is true if the contract is ready to accept a new universe root submission
     */
    function isReadyForUniverseRootSubmission(
        uint256 universeIdx
    ) external view returns (bool isReady);

    /**
     * @notice Returns true if the system is ready to accept challenges to the last
     * submitted ownership root
     * @return Whether the system is ready to accept challenges
     */
    function isReadyForChallenge() external view returns (bool);

    /**
     * @notice Returns data about the status of the current challenge,
     * taking into account the time passed, so that the actual level
     * can be less than the level explicitly stored, or just settled.
     * @return isSettled Whether the current challenge process is settled
     * @return actualLevel The level at which the last challenge process is, accounting for
     * @return nJumps The number of challenge levels already accounted for when
     * taking time into account
     */
    function getCurrentChallengeStatus()
        external
        view
        returns (
            bool isSettled,
            uint8 actualLevel,
            uint8 nJumps
        );

    /**
     * @notice Returns true if the universe verse is ready for challenge
     * taking into account the time passed
     * @param universeIdx universe index
     * @return isReady is true if the universe verse is ready for challenge
     */
    function isUniverseRootReadyForChallenge(
        uint256 universeIdx
    ) external view returns (bool isReady);

    /**
     * @notice Returns true if the asset cannot undergo any ownership change
     * because of its export process
     * @dev This function requires both the assetId and the owner as inputs,
     * because an asset is blocked only if the owner coincides with
     * the address that made the request earlier.
     * This view function gathers export info from storage and calls isAssetBlockedByExportPure
     * @param assetId the id of the asset
     * @param currentOwner the current owner of the asset
     * @return whether the asset is blocked or not
     */
    function isAssetBlockedByExport(uint256 assetId, address currentOwner)
        external
        view
        returns (bool);

    /**
     * @notice Returnss true if the asset cannot undergo any ownership change
     * @dev Pure version of isAssetBlockedByExport
     * @param currentOwner The current owner of the asset
     * @param currentVerse The current txVerse
     * @param requestOwner The address of the owner who started the export request
     * @param requestVerse The txVerse at which the export request was made
     * @param completedVerse The txVerse at which the export process was completed.
     * Should be 0 if process is not completed.
     * @return whether the asset is blocked or not
     */
    function isAssetBlockedByExportPure(
        address currentOwner,
        uint256 currentVerse,
        address requestOwner,
        uint256 requestVerse,
        uint256 completedVerse
    ) external pure returns (bool);
}

File 14 of 17 : IGovernance.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract for querying and using isAwaitingGovernance 
 @author Freeverse.io, www.freeverse.io
*/

interface IGovernance {

    /**
     * @notice Returns the awaitGovernance bool stored in the Storage contract
     *  WARNING: this function can revert if the claim does not exist in storage,
     *  use hasGovernance() before calling this function to avoid unwanted reverts.
     * @return the awaitGovernance bool stored in the Storage contract
     */
    function isAwaitingGovernance() external view returns (bool);

    /**
     * @notice Returns true if the Storage contract stores as claim(1,0)
     *  the expected data for a isAwaitingGovernance
     * @return true if the stored isAwaitingGovernance is as expected
     */
    function hasGovernance() external view returns (bool);

    /**
     * @notice Returns true if the provided inputs follow the 
     *  the expected data for a isAwaitingGovernance
     * @param str the provided string that identifies the claim as referring to 'isAwaitingGovernance'
     * @return true if the provided inputs follow the expected data for a isAwaitingGovernance
     */
    function claimIsValidGovernance(string memory str) external pure returns (bool);

    /**
     * @notice Reverts unless the Storage contract stores as claim(1,0)
     *  the expected data for a isAwaitingGovernance
     */
    function assertValidGovernance() external view; 
}

File 15 of 17 : IChallengeLibStatus.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @author Freeverse.io, www.freeverse.io
 @dev Interface to contract with pure function to compute the status of a challenge
*/

interface IChallengeLibStatus {
    /**
     * @dev Computes if the system is ready to accept a new TX Batch submission
     *      Data from storage is fetched previous to passing to this function.
     */
    function isInChallengePeriodFinishedPhasePure(
        uint256 txRootsCurrentVerse,
        uint256 ownershipSubmissionTimeCurrent,
        uint256 challengeWindowCurrent,
        uint256 txSubmissionTimeCurrent,
        uint256 blockTimestamp,
        uint8 challengesLevel
    ) external pure returns (bool isChallengeOver, uint8 actualLevel);

    /**
    * @dev Pure function to compute if the current challenge is settled already,
           or if due to time passing, one or more challenges have been tacitly accepted.
           In such case, the challenge processs reduces 2 levels per challenge accepted.
           inputs:
            currentTime: now, in secs, as return by block.timstamp
            lastChallTime: time at which the last challenge was received (at level 0, time of submission of ownershipRoot)
            challengeWindow: amount of time available for submitting a new challenge
            writtenLevel: the last stored level of the current challenge game
           returns:
            isSettled: if true, challenges are still accepted
            actualLevel: the level at which the challenge truly is, taking time into account.
            nJumps: the number of challenges tacitly accepted, taking time into account.
    */
    function computeChallStatus(
        uint256 currentTime,
        uint256 lastTxSubmissionTime,
        uint256 lastChallTime,
        uint256 challengeWindow,
        uint8 writtenLevel
    )
        external
        pure
        returns (
            bool isSettled,
            uint8 actualLevel,
            uint8 nJumps
        );
}

File 16 of 17 : IBypassedOwnershipVerses.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract for querying and using BypassedOwnershipVerses 
 @author Freeverse.io, www.freeverse.io
*/

interface IBypassedOwnershipVerses {

    /**
     * @notice Returns true if the queried verse has been bypassed
     * @param verse, the verse to query about bypassed state
     * @return true if the queried verse has been bypassed
     */
    function isBypassed(uint256 verse) external view returns (bool);

    /**
     * @notice Returns true if the Storage contract has been extended
     *  with claim(2,0), as expected to be able store bypassed verses
     * @return true if the Storage contract has been extended
     *  with claim(2,0)
     */
    function hasClaimForBypassedOwnershipVerses() external view returns (bool);

    /**
     * @notice Reverts unless the Storage contract has been extended
     *  with claim(2,0), as expected to be able store bypassed verses
     */
    function assertValidBypassedOwnershipVerses() external view; 
}

File 17 of 17 : IBlackholeId.sol
// SPDX-License-Identifier: MIT
pragma solidity =0.8.11;

/**
 @title Interface to contract for querying and using blackholeId 
 @author Freeverse.io, www.freeverse.io
*/

interface IBlackholeId {

    /**
     * @notice Returns the blackholeId stored in the Storage contract
     *  WARNING: this function can revert if no claims exist in storage,
     *  use hasBlackholeId() before calling this function to avoid unwanted reverts.
     * @return blackholeId the blackholeId
     */
    function blackholeId() external view returns (uint8);

    /**
     * @notice Returns true if the Storage contract stores as claim(0,0)
     *  the expected data for a BlackholeID
     * @return true if the stored blackholeId is as expected
     */
    function hasBlackholeId() external view returns (bool);

    /**
     * @notice Returns true if the provided inputs follow the 
     *  the expected data for a BlackholeID
     * @param number the provided value for blackholeId
     * @param str the provided string that identifies the claim as referring to 'blackholeId'
     * @return true if the provided inputs follow the expected data for a BlackholeID
     */
    function claimIsValidBlackholeID(uint256 number, string memory str) external pure returns (bool);

    /**
     * @notice Reverts unless the Storage contract stores as claim(0,0)
     *  the expected data for a BlackholeID
     */
    function assertValidBlackholeId() external view; 

    /**
     * @notice Returns true if the provided assetId encodes a blackholeId that
     *  matches the provided id 
     * @param assetId the assetId that encodes a certain blackholeId
     * @param id the blackholeId against which to compare
     * @return true if the provided assetId encodes a blackholeId that
     *  matches the provided id
     */
    function hasCorrectBlackholeId(uint256 assetId, uint8 id) external pure returns (bool);

    /**
     * @notice Returns true if the provided assetId encodes a blackholeId that
     *  matches the blackholeId in the Storage contract
     * @param assetId the assetId that encodes a certain blackholeId
     * @return true if the provided assetId encodes a blackholeId that
     *  matches the blackholeId in the Storage contract
     */
    function hasCorrectBlackholeId(uint256 assetId) external view returns (bool);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"storageAddress","type":"address"},{"internalType":"address","name":"writer","type":"address"},{"internalType":"address","name":"info","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"universeIdx","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"}],"name":"BypassUniverseVerse","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"}],"name":"BypassVerse","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"newRoot","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"}],"name":"NewOwnershipRoot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"newRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"nTXs","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"levelsPerChallenge","type":"uint8"},{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"},{"indexed":false,"internalType":"string","name":"ipfsCid","type":"string"}],"name":"NewTXsRoot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"universeIdx","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"newRoot","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"},{"indexed":false,"internalType":"string","name":"ipfsCid","type":"string"}],"name":"NewUniverseRoot","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"},{"indexed":false,"internalType":"string","name":"ipfsCid","type":"string"}],"name":"OwnershipIPFSAtVerse","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"newProposedRoot","type":"bytes32"}],"name":"OwnershipRootMismatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"version","type":"uint32"}],"name":"OwnershipTxFormatVersion","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"verse","type":"uint256"}],"name":"UnavailableTXData","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"universeIdx","type":"uint256"},{"indexed":false,"internalType":"bool","name":"requested","type":"bool"},{"indexed":false,"internalType":"bool","name":"confirmed","type":"bool"}],"name":"UniverseClosure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"universeIdx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"verse","type":"uint256"}],"name":"WrongUniverseRoot","type":"event"},{"inputs":[{"internalType":"bytes","name":"serialized","type":"bytes"}],"name":"MTLeaf","outputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"serialized","type":"bytes"}],"name":"MTPos","outputs":[{"internalType":"uint256","name":"pos","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"serialized","type":"bytes"}],"name":"MTProof","outputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"leafHash","type":"bytes32"},{"internalType":"uint256","name":"leafPos","type":"uint256"}],"name":"MTVerify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"},{"internalType":"bytes","name":"MTData","type":"bytes"}],"name":"MTVerifySerialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"OWNERSHIP_TXFORMAT_VERSION","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_info","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_sto","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_writer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"leafPos","type":"uint256"},{"internalType":"bytes32[]","name":"leaves","type":"bytes32[]"},{"internalType":"uint256","name":"nLevels","type":"uint256"}],"name":"buildProof","outputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"universeIdx","type":"uint256"},{"internalType":"uint256","name":"verse","type":"uint256"}],"name":"bypassCurrentUniverseVerse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint32","name":"nEntries","type":"uint32"}],"name":"bytesToBytes32ArrayWithoutHeader","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"nTXs","type":"uint256"},{"internalType":"uint256","name":"nLeavesPerChallenge","type":"uint256"}],"name":"computeLevelVerifiableOnChain","outputs":[{"internalType":"uint8","name":"levelVeriableByBC","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"universeIdx","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"confirmUniverseClosure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"txVerse","type":"uint256"}],"name":"deactivateGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"verse","type":"uint256"},{"internalType":"string","name":"ipfsCid","type":"string"}],"name":"emitOwnershipIPFSAtVerse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"hash_node","outputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"isReadyForOwnershipSubmission","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"license","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"leaves","type":"bytes32[]"},{"internalType":"uint256","name":"nLevels","type":"uint256"}],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"prefixed","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"msgHash","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"recoverAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"msgHash","type":"bytes32"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"recoverAddrFromBytes","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"universeIdx","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"removeUniverseClosureRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"universeIdx","type":"uint256"},{"internalType":"uint256","name":"validUntil","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"requestUniverseClosure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"universeIdx","type":"uint256"},{"internalType":"bytes32","name":"newRoot","type":"bytes32"},{"internalType":"bytes32","name":"prevTransRoot","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"string","name":"ipfsCid","type":"string"}],"name":"setNewUniverseRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"verse","type":"uint256"},{"internalType":"bytes32","name":"ownershipRoot","type":"bytes32"},{"internalType":"uint32","name":"txFormatVersion","type":"uint32"}],"name":"submitNewOwnershipRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"verse","type":"uint256"},{"internalType":"bytes32","name":"txRoot","type":"bytes32"},{"internalType":"uint256","name":"nTXs","type":"uint256"},{"internalType":"uint32","name":"txFormatVersion","type":"uint32"},{"internalType":"string","name":"ipfsCid","type":"string"}],"name":"submitNewTXsRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"verse","type":"uint256"},{"internalType":"uint256","name":"universeIdx","type":"uint256"},{"internalType":"bytes32","name":"newRoot","type":"bytes32"},{"internalType":"bytes32","name":"prevTransRoot","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"string","name":"ipfsCid","type":"string"}],"name":"submitNewUniverseRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"serialized","type":"bytes"}],"name":"txGetType","outputs":[{"internalType":"uint8","name":"txType","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"verse","type":"uint256"}],"name":"unavailableTXData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"verse","type":"uint256"}],"name":"wrongTXDataRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"universeIdx","type":"uint256"},{"internalType":"uint256","name":"verse","type":"uint256"}],"name":"wrongUniverseRoot","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60e06040523480156200001157600080fd5b5060405162005fee38038062005fee8339810160408190526200003491620000fa565b806001600160a01b031663c34143d76040518163ffffffff1660e01b815260040160006040518083038186803b1580156200006e57600080fd5b505afa15801562000083573d6000803e3d6000fd5b505050506001600160a01b0383811660805282811660a052811660c052604051600181527f035f5fe90b7adb8acea2f038186ecd3db2b7555b7e47bc0250ef5b4a88a6905f9060200160405180910390a150505062000144565b80516001600160a01b0381168114620000f557600080fd5b919050565b6000806000606084860312156200011057600080fd5b6200011b84620000dd565b92506200012b60208501620000dd565b91506200013b60408501620000dd565b90509250925092565b60805160a05160c051615c6d6200038160003960008181610474015281816105ce015281816110ed015281816118930152818161200f015281816130c60152818161314e01528181613b2901528181613f800152818161475a0152614c3e0152600081816102e90152818161092d015281816109c701528181610a5a01528181610ed101528181611362015281816114d00152818161156401528181611b43015281816122c50152818161233f01528181612c01015281816139b701528181613d1d015281816142d60152818161464a015281816146c201528181614a7f01528181614d1201528181614dde0152614e7a0152600081816103e101528181610513015281816106e8015281816107da0152818161087e01528181610b0001528181610c7701528181610dcf015281816110010152818161118a0152818161120a0152818161165001528181611716015281816117bc0152818161198e01528181611a8a01528181611c5201528181611dc501528181611f1b015281816121ed01528181612809015281816128cf0152818161297501528181612a4c01528181612b4801528181612cc201528181612e2501528181612ed901528181612f7a015281816131d7015281816135d30152818161372d015281816137f30152818161389901528181613a7701528181613c28015281816140020152818161415c015281816142220152818161437f0152818161446f015281816144fd015281816145a2015281816148630152818161495a0152614b390152615c6d6000f3fe608060405234801561001057600080fd5b50600436106101fa5760003560e01c80638bf82e971161011a578063ce7abcb8116100ad578063dcf4318c1161007c578063dcf4318c146104bd578063e5df669f146104d0578063f0af24e7146104e3578063f47dd9b1146104f6578063f74a6d8b146104fe57600080fd5b8063ce7abcb814610449578063d00920521461045c578063d0ba06f01461046f578063d28757cc1461049657600080fd5b8063a92550ad116100e9578063a92550ad146103dc578063adc72df714610403578063b701017f14610423578063bc0b907d1461043657600080fd5b80638bf82e97146103845780638c9ac90a146103a15780639a95ce05146103b4578063a11c758f146103c757600080fd5b80633033951d116101925780635f4db235116101615780635f4db235146103365780636875c5b9146103495780636b87d24c1461035c5780638b0c66071461037157600080fd5b80633033951d146102be5780633d43a239146102d15780634c04896f146102e45780635f2d1f8d1461032357600080fd5b80631f275713116101ce5780631f2757131461026257806324998252146102755780632c19dfba146102885780632f4e29121461029b57600080fd5b8062d4a20f146101ff5780630f254e9814610214578063186b7bf6146102275780631cff8b101461023a575b600080fd5b61021261020d366004614eda565b610511565b005b610212610222366004614f44565b610afe565b610212610235366004614faf565b610f82565b61024f6102483660046150a7565b6040015190565b6040519081526020015b60405180910390f35b61024f6102703660046150e3565b6115fb565b6102126102833660046150fc565b61164e565b610212610296366004615191565b611c50565b6102ae6102a93660046151dc565b611d71565b6040519015158152602001610259565b61024f6102cc366004614eda565b611d98565b6102126102df366004615222565b611dc3565b61030b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610259565b61024f610331366004615311565b6123fd565b6102ae610344366004615355565b612760565b6102126103573660046153ab565b612807565b610364612cbe565b6040516102599190615463565b61030b61037f3660046151dc565b612d4b565b61038c600181565b60405163ffffffff9091168152602001610259565b6102126103af3660046150e3565b612e23565b6102126103c2366004614eda565b612f76565b61024f6103d53660046150a7565b6020015190565b61030b7f000000000000000000000000000000000000000000000000000000000000000081565b610416610411366004615496565b61326e565b60405161025991906154e5565b610212610431366004614f44565b6135d1565b6102126104443660046150e3565b613a5d565b6102126104573660046150e3565b613a75565b61041661046a366004615529565b613d91565b61030b7f000000000000000000000000000000000000000000000000000000000000000081565b6104ab6104a43660046150a7565b6001015190565b60405160ff9091168152602001610259565b6104ab6104cb366004614eda565b613e4b565b61030b6104de366004615585565b613e7d565b6104166104f13660046150a7565b613ee5565b6102ae613f7c565b61021261050c366004614f44565b614000565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b65c630b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561056f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059391906155c2565b6001600160a01b0316336001600160a01b0316146105cc5760405162461bcd60e51b81526004016105c3906155eb565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663eeab68fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561062a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064e9190615632565b6106d05760405162461bcd60e51b815260206004820152604760248201527f557064617465733a3a62797061737343757272656e74556e697665727365566560448201527f7273653a2073797374656d206e6f74206177616974696e6720666f7220476f7660648201526665726e616e636560c81b608482015260a4016105c3565b604051631000260b60e21b81526004810183905281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634000982c90602401602060405180830381865afa158015610737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075b919061564d565b146107ce5760405162461bcd60e51b815260206004820152603d60248201527f557064617465733a3a62797061737343757272656e74556e697665727365566560448201527f7273653a20696e636f72726563742070726f766964656420766572736500000060648201526084016105c3565b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016634c552d2e8461080b60018661567c565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610870919061564d565b905060006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166313efebd4856108af60018761567c565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa1580156108f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610914919061564d565b604051637815415d60e11b8152600481018690529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f02a82ba906024016020604051808303816000875af115801561097e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a2919061564d565b50604051632383313160e01b81526004810185905260248101839052604481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323833131906064016020604051808303816000875af1158015610a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3c919061564d565b5060405163015e397b60e01b815260048101859052602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063015e397b90604401600060405180830381600087803b158015610aa657600080fd5b505af1158015610aba573d6000803e3d6000fd5b50505050827fcbb9e9943b702d9e3c8964bfc050c551c571d6fbcb56cb2004ed2c6509c766b385604051610af091815260200190565b60405180910390a250505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8091906155c2565b6001600160a01b0316336001600160a01b031614610bb05760405162461bcd60e51b81526004016105c390615693565b60408051606060208201819052601460808301527314995b5bdd9950db1bdcdd5c9954995c5d595cdd60621b60a0830152918101869052908101849052600090610c139060c0015b604051602081830303815290604052805190602001206115fb565b9050610c558184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f0000000000000000000000000000000000000000000000000000000000000000169063b4a750b690602401602060405180830381865afa158015610cbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce291906155c2565b6001600160a01b031614610d545760405162461bcd60e51b815260206004820152603360248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20736960448201527219db985d1d5c99481b9bdd0818dbdc9c9958dd606a1b60648201526084016105c3565b428411610db95760405162461bcd60e51b815260206004820152602d60248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20726560448201526c1c5d595cdd08195e1c1a5c9959609a1b60648201526084016105c3565b604051635e1d948760e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bc3b290e90602401602060405180830381865afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e429190615632565b15610ead5760405162461bcd60e51b815260206004820152603560248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20756e6044820152741a5d995c9cd948185b1c9958591e4818db1bdcd959605a1b60648201526084016105c3565b604051637983b61d60e11b81526004810186905260006024820181905260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f3076c3a90606401600060405180830381600087803b158015610f1d57600080fd5b505af1158015610f31573d6000803e3d6000fd5b505060408051888152600060208201819052918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e7925060600190505b60405180910390a15050505050565b63ffffffff8116600114610ffe5760405162461bcd60e51b815260206004820152603a60248201527f557064617465733a3a7375626d69744e65774f776e657273686970526f6f743a60448201527f20696e636f7272656374207478466f726d617456657273696f6e00000000000060648201526084016105c3565b827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611081919061564d565b146110eb5760405162461bcd60e51b815260206004820152603460248201527f6572726f723a207375626d69744e65774f776e657273686970526f6f7420666f6044820152737220616e20696e636f727265637420766572736560601b60648201526084016105c3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631624efa96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190615632565b80156112015750604051632bacd5dd60e11b8152600060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635759abba90602401602060405180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd919061564d565b8214155b1561141c5760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fed1252a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611266573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128a91906155c2565b604051636f1e853360e01b81523360048201529091506001600160a01b03821690636f1e853390602401602060405180830381865afa1580156112d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f59190615632565b6113605760405162461bcd60e51b815260206004820152603660248201527f557064617465733a3a7375626d69744e65774f776e657273686970526f6f743a604482015275081cdd185ad95c881b9bdd081c9959da5cdd195c995960521b60648201526084016105c3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630d29fb546040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113bb57600080fd5b505af11580156113cf573d6000803e3d6000fd5b50505050837f890c5b8d04c3b93366cc6f7b68f7b2fd236cf9388ac44b15ef0d59336abcf3d08460405161140591815260200190565b60405180910390a26114168461437c565b50505050565b611424613f7c565b6114b15760405162461bcd60e51b815260206004820152605260248201527f6e6f7420726561647920666f72206f776e657273686970207375626d6973736960448201527f6f6e3a207665727365206e6f7420736574746c6564206f72206e657720545873606482015271081b9bdd081cdd589b5a5d1d1959081e595d60721b608482015260a4016105c3565b6040516306bee10560e01b8152600481018390524260248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906306bee105906044016020604051808303816000875af1158015611521573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611545919061564d565b604051632bf660ef60e21b8152600060048201523360248201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063afd983bc90604401600060405180830381600087803b1580156115b057600080fd5b505af11580156115c4573d6000803e3d6000fd5b50506040518392508591507faf90c4aa6579d46f1d1728fd0113c96d153d42aaa5ab1f5bc241a05c4fc622af90600090a350505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d091906155c2565b6001600160a01b0316336001600160a01b0316146117005760405162461bcd60e51b81526004016105c390615693565b604051635e1d948760e11b8152600481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bc3b290e90602401602060405180830381865afa158015611765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117899190615632565b156117a65760405162461bcd60e51b81526004016105c3906156d9565b60405163249f9e7360e11b8152600481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063493f3ce690602401602060405180830381865afa15801561180b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182f919061564d565b851461187d5760405162461bcd60e51b815260206004820152601c60248201527f707265765472616e73526f6f7420646f6573206e6f74206d617463680000000060448201526064016105c3565b60405163666beda160e01b8152600481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063666beda190602401602060405180830381865afa1580156118e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119069190615632565b6119785760405162461bcd60e51b815260206004820152603960248201527f6e6f7420726561647920666f7220756e69766572736520726f6f74207375626d60448201527f697373696f6e3a207665727365206e6f7420736574746c65640000000000000060648201526084016105c3565b60405163213f03fb60e21b8152600481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906384fc0fec90602401602060405180830381865afa1580156119dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a019190615632565b611b1d576000611a268787604051602001610bf8929190918252602082015260400190565b9050611a688186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018a90526001600160a01b03918216917f0000000000000000000000000000000000000000000000000000000000000000169063b4a750b690602401602060405180830381865afa158015611ad1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af591906155c2565b6001600160a01b031614611b1b5760405162461bcd60e51b81526004016105c390615724565b505b604051632383313160e01b815260048101889052602481018790524260448201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323833131906064016020604051808303816000875af1158015611b94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb8919061564d565b9050808914611c095760405162461bcd60e51b815260206004820152601f60248201527f6572726f723a20696e636f727265637420756e6976657273652076657273650060448201526064016105c3565b8087897f3622597e9085739b48cf129e1f6dfb4cb8c29aa6bccc1d92bc07791eb2fd19888686604051611c3d929190615797565b60405180910390a4505050505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663aba3e1116040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd291906155c2565b6001600160a01b0316336001600160a01b031614611d325760405162461bcd60e51b815260206004820181905260248201527f4f6e6c792072656c6179206f662054587320697320617574686f72697a65642e60448201526064016105c3565b827ff09c0c2e1067d84ab49d3bff959e45870f3417b16c65199accc451bca46e0d508383604051611d64929190615797565b60405180910390a2505050565b6000611d8f83611d8084613ee5565b60408501516020860151612760565b90505b92915050565b600081158015611da6575082155b15611db357506000611d92565b5060009182526020526040902090565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663aba3e1116040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4591906155c2565b6001600160a01b0316336001600160a01b031614611ea55760405162461bcd60e51b815260206004820181905260248201527f4f6e6c792072656c6179206f662054587320697320617574686f72697a65642e60448201526064016105c3565b63ffffffff8316600114611f185760405162461bcd60e51b815260206004820152603460248201527f557064617465733a3a7375626d69744e6577545873526f6f743a20696e636f726044820152733932b1ba103a3c2337b936b0ba2b32b939b4b7b760611b60648201526084016105c3565b857f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9b919061564d565b611fa69060016157ab565b1461200a5760405162461bcd60e51b815260206004820152602e60248201527f6572726f723a207375626d69744e6577545873526f6f7420666f7220616e206960448201526d6e636f727265637420766572736560901b60648201526084016105c3565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ad71247e6040518163ffffffff1660e01b81526004016040805180830381865afa15801561206a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208e91906157c3565b91509150816121055760405162461bcd60e51b815260206004820152603860248201527f6e6f7420726561647920746f20616363657074206e6577205458207375626d6960448201527f7373696f6e2c207665727365206e6f7420736574746c6564000000000000000060648201526084016105c3565b8060ff166001148061211a57508060ff166002145b61217e5760405162461bcd60e51b815260206004820152602f60248201527f7061737420766572736520656e64656420757020736574746c696e6720696e2060448201526e1a5b98dbdc9c9958dd081b195d995b608a1b60648201526084016105c3565b856121e95786156121e95760405162461bcd60e51b815260206004820152602f60248201527f696e20612076657273652077697468206e6f205458732c20746865205458526f60448201526e1bdd081b5d5cdd081899481b9d5b1b608a1b60648201526084016105c3565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663456c405a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226d91906157fa565b90506000612283886104cb60ff851660026158fb565b6040516323da0e0960e21b8152600481018b9052426024820152604481018a905260ff8086166064830152821660848201529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690638f6838249060a4016020604051808303816000875af115801561230e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612332919061564d565b905060018111156123b1577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634bb278f36040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561239857600080fd5b505af11580156123ac573d6000803e3d6000fd5b505050505b808a7f6f3984a8056b744a2405c513c3027efbcc8f00fb16be25a2e3fb772238b3455d8b868b8b6040516123e89493929190615907565b60405180910390a35050505050505050505050565b600081612426578260008151811061241757612417615934565b60200260200101519050611d92565b60006124338360026158fb565b905083518110156124ac5760405162461bcd60e51b815260206004820152603860248201527f6d65726b6c65526f6f743a206e6f7420656e6f756768206c6576656c7320676960448201527f76656e20746865206e756d626572206f66206c6561766573000000000000000060648201526084016105c3565b6124b7600282615960565b90506000816001600160401b038111156124d3576124d3614fe4565b6040519080825280602002602001820160405280156124fc578160200160208202803683370190505b50905060006002865161250f9190615960565b905060005b818110156125a8576125798761252b836002615974565b8151811061253b5761253b615934565b6020026020010151888360026125519190615974565b61255c9060016157ab565b8151811061256c5761256c615934565b6020026020010151611d98565b83828151811061258b5761258b615934565b6020908102919091010152806125a081615993565b915050612514565b50600286516125b791906159ae565b1561261a576125ef86600188516125ce919061567c565b815181106125de576125de615934565b60200260200101516000801b611d98565b82828151811061260157612601615934565b60209081029190910101526126176001826157ab565b90505b60015b858160ff16101561273957612633600285615960565b93506126406002836159ae565b1561266057612650600283615960565b61265b9060016157ab565b61266b565b61266b600283615960565b915083821115612679578391505b60005b828110156126e8576126b984612693836002615974565b815181106126a3576126a3615934565b6020026020010151858360026125519190615974565b8482815181106126cb576126cb615934565b6020908102919091010152806126e081615993565b91505061267c565b50815b84811015612726576000801b84828151811061270957612709615934565b60209081029190910101528061271e81615993565b9150506126eb565b5080612731816159c2565b91505061261d565b508160008151811061274d5761274d615934565b6020026020010151935050505092915050565b6000805b84518163ffffffff1610156127f05761277e6002846159ae565b6127a55761279e84868363ffffffff168151811061256c5761256c615934565b93506127d1565b6127ce858263ffffffff16815181106127c0576127c0615934565b602002602001015185611d98565b93505b6127dc600284615960565b9250806127e8816159e2565b915050612764565b50811580156127fe57508285145b95945050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612865573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288991906155c2565b6001600160a01b0316336001600160a01b0316146128b95760405162461bcd60e51b81526004016105c390615693565b604051635e1d948760e11b8152600481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bc3b290e90602401602060405180830381865afa15801561291e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129429190615632565b1561295f5760405162461bcd60e51b81526004016105c3906156d9565b60405163249f9e7360e11b8152600481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063493f3ce690602401602060405180830381865afa1580156129c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e8919061564d565b8514612a365760405162461bcd60e51b815260206004820152601c60248201527f707265765472616e73526f6f7420646f6573206e6f74206d617463680000000060448201526064016105c3565b60405163213f03fb60e21b8152600481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906384fc0fec90602401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190615632565b612bdb576000612ae48787604051602001610bf8929190918252602082015260400190565b9050612b268186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018a90526001600160a01b03918216917f0000000000000000000000000000000000000000000000000000000000000000169063b4a750b690602401602060405180830381865afa158015612b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb391906155c2565b6001600160a01b031614612bd95760405162461bcd60e51b81526004016105c390615724565b505b604051632383313160e01b815260048101889052602481018790524260448201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323833131906064016020604051808303816000875af1158015612c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c76919061564d565b90508087897f3622597e9085739b48cf129e1f6dfb4cb8c29aa6bccc1d92bc07791eb2fd19888686604051612cac929190615797565b60405180910390a45050505050505050565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636b87d24c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612d1e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d469190810190615a06565b905090565b6000806000808451604114612d665760009350505050611d92565b50505060208201516040830151604184015160ff16601b811015612d9257612d8f601b82615a73565b90505b8060ff16601b14158015612daa57508060ff16601c14155b15612dbb5760009350505050611d92565b60408051600081526020810180835288905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015612e0e573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b65c630b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906155c2565b6001600160a01b0316336001600160a01b031614612ed55760405162461bcd60e51b81526004016105c3906155eb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630738ccce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f59919061564d565b90506000612f68838383614758565b612f718361437c565b505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fed1252a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffa91906155c2565b604051636f1e853360e01b81523360048201529091506001600160a01b03821690636f1e853390602401602060405180830381865afa158015613041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130659190615632565b6130c45760405162461bcd60e51b815260206004820152602a60248201527f6f6e6c79207374616b65722063616e207265706f72742077726f6e6720756e696044820152691d995c9cd9481c9bdbdd60b21b60648201526084016105c3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f47dd9b16040518163ffffffff1660e01b8152600401602060405180830381865afa158015613122573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131469190615632565b806131ce57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631624efa96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ce9190615632565b156132645760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613233573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613257919061564d565b90506132628161437c565b505b612f718383614b21565b60608161335a5782516001146132e15760405162461bcd60e51b815260206004820152603260248201527f6275696c6450726f6f663a206c6561766573206c656e677468206d75737420626044820152710652030206966206e4c6576656c73203d20360741b60648201526084016105c3565b83156133555760405162461bcd60e51b815260206004820152603760248201527f6275696c6450726f6f663a206c656166506f73206d757374206265203020696660448201527f207468657265206973206f6e6c79206f6e65206c65616600000000000000000060648201526084016105c3565b6135ca565b60006133678360026158fb565b9050808451146133ca5760405162461bcd60e51b815260206004820152602860248201527f6e756d626572206f66206c6561766573206973206e6f74203d20706f7728322c6044820152676e4c6576656c732960c01b60648201526084016105c3565b826001600160401b038111156133e2576133e2614fe4565b60405190808252806020026020018201604052801561340b578160200160208202803683370190505b5091506134196002866159ae565b15613447578361342a60018761567c565b8151811061343a5761343a615934565b602002602001015161346c565b836134538660016157ab565b8151811061346357613463615934565b60200260200101515b8260008151811061347f5761347f615934565b60200260200101818152505060005b61349960018561567c565b8160ff1610156135c7576134ae600283615960565b91506134bb600287615960565b955060005b8281101561352c576134fd866134d7836002615974565b815181106134e7576134e7615934565b6020026020010151878360026125519190615974565b86828151811061350f5761350f615934565b60209081029190910101528061352481615993565b9150506134c0565b506135386002876159ae565b15613566578461354960018861567c565b8151811061355957613559615934565b602002602001015161358b565b846135728760016157ab565b8151811061358257613582615934565b60200260200101515b83613597836001615a73565b60ff16815181106135aa576135aa615934565b6020908102919091010152806135bf816159c2565b91505061348e565b50505b9392505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561362f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365391906155c2565b6001600160a01b0316336001600160a01b0316146136835760405162461bcd60e51b81526004016105c390615693565b60408051606060208201819052600e60808301526d436f6e6669726d436c6f7375726560901b60a08301529181018690529081018490526000906136c99060c001610bf8565b905061370b8184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f0000000000000000000000000000000000000000000000000000000000000000169063b4a750b690602401602060405180830381865afa158015613774573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061379891906155c2565b6001600160a01b0316146137be5760405162461bcd60e51b81526004016105c390615a98565b4284116137dd5760405162461bcd60e51b81526004016105c390615ae5565b604051635e1d948760e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bc3b290e90602401602060405180830381865afa158015613842573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138669190615632565b156138835760405162461bcd60e51b81526004016105c390615b2c565b6040516395592de760e01b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906395592de790602401602060405180830381865afa1580156138e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061390c9190615632565b6139935760405162461bcd60e51b815260206004820152604c60248201527f72657175657374556e697665727365436c6f737572653a20756e69766572736560448201527f20636c6f73757265206d75737420626520726571756573746564206265666f7260648201526b6520636f6e6669726d696e6760a01b608482015260a4016105c3565b604051637983b61d60e11b81526004810186905260016024820181905260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f3076c3a90606401600060405180830381600087803b158015613a0357600080fd5b505af1158015613a17573d6000803e3d6000fd5b505060408051888152600160208201819052918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e792506060019050610f73565b613a6981600033614758565b613a728161437c565b50565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b65c630b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af791906155c2565b6001600160a01b0316336001600160a01b031614613b275760405162461bcd60e51b81526004016105c3906155eb565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663eeab68fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba99190615632565b613c255760405162461bcd60e51b815260206004820152604160248201527f557064617465733a3a64656163746976617465476f7665726e616e63653a207360448201527f797374656d206e6f74206177616974696e6720666f7220476f7665726e616e636064820152606560f81b608482015260a4016105c3565b807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ca8919061564d565b14613d1b5760405162461bcd60e51b815260206004820152603760248201527f557064617465733a3a64656163746976617465476f7665726e616e63653a206960448201527f6e636f72726563742070726f766964656420766572736500000000000000000060648201526084016105c3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663baebc7986040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613d7657600080fd5b505af1158015613d8a573d6000803e3d6000fd5b5050505050565b606060008263ffffffff166001600160401b03811115613db357613db3614fe4565b604051908082528060200260200182016040528015613ddc578160200160208202803683370190505b50905060005b8363ffffffff168163ffffffff161015613e4257613e016020866157ab565b9450600085870151905080838363ffffffff1681518110613e2457613e24615934565b60209081029190910101525080613e3a816159e2565b915050613de2565b50949350505050565b6003815b80841115613e765781613e61816159c2565b9250613e6f90508382615974565b9050613e4f565b5092915050565b6040805160008082526020820180845287905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa158015613ed1573d6000803e3d6000fd5b5050604051601f1901519695505050505050565b60606000602060408451613ef99190615b7b565b613f039190615ba0565b9050613f10816020615bc3565b613f1b906040615bef565b63ffffffff16835114613f705760405162461bcd60e51b815260206004820152601b60248201527f696e636f72726563742073657269616c697a6564206c656e677468000000000060448201526064016105c3565b6135ca83604083613d91565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f47dd9b16040518163ffffffff1660e01b8152600401602060405180830381865afa158015613fdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d469190615632565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561405e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061408291906155c2565b6001600160a01b0316336001600160a01b0316146140b25760405162461bcd60e51b81526004016105c390615693565b60408051606060208201819052600e60808301526d52657175657374436c6f7375726560901b60a08301529181018690529081018490526000906140f89060c001610bf8565b905061413a8184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f0000000000000000000000000000000000000000000000000000000000000000169063b4a750b690602401602060405180830381865afa1580156141a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141c791906155c2565b6001600160a01b0316146141ed5760405162461bcd60e51b81526004016105c390615a98565b42841161420c5760405162461bcd60e51b81526004016105c390615ae5565b604051635e1d948760e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063bc3b290e90602401602060405180830381865afa158015614271573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142959190615632565b156142b25760405162461bcd60e51b81526004016105c390615b2c565b604051637983b61d60e11b81526004810186905260016024820152600060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f3076c3a90606401600060405180830381600087803b15801561432257600080fd5b505af1158015614336573d6000803e3d6000fd5b505060408051888152600160208201526000918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e792506060019050610f73565b807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156143db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143ff919061564d565b1461446b5760405162461bcd60e51b815260206004820152603660248201527f557064617465733a3a5f62797061737343757272656e7456657273653a20696e604482015275636f72726563742070726f766964656420766572736560501b60648201526084016105c3565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663657aea9f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156144cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144ef919061564d565b8214905080614596576000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166322af10f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015614559573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061457d919061564d565b90506145938261458e8360016157ab565b614dc1565b50505b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663fd5a64996145d260018661567c565b6040518263ffffffff1660e01b81526004016145f091815260200190565b602060405180830381865afa15801561460d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614631919061564d565b6040516375da387560e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906375da387590602401600060405180830381600087803b15801561469657600080fd5b505af11580156146aa573d6000803e3d6000fd5b505060405163e889d33760e01b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316925063e889d3379150602401600060405180830381600087803b15801561471057600080fd5b505af1158015614724573d6000803e3d6000fd5b50506040518592507fcfa8dd9c1dd3c45573e593c8000f407cbeb29fcd04a9bd1e17a8af27db1391469150600090a2505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f47dd9b16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147da9190615632565b6148605760405162461bcd60e51b815260206004820152605d6024820152600080516020615c1883398151915260448201527f6f6e675458735075626c69736865643a2073797374656d206e6f74206177616960648201527f74696e6720666f72206f776e657273686970207375626d697373696f6e000000608482015260a4016105c3565b827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148e3919061564d565b146149565760405162461bcd60e51b81526020600482015260496024820152600080516020615c1883398151915260448201527f6f6e675458735075626c69736865643a20696e636f72726563742070726f766960648201526864656420766572736560b81b608482015260a4016105c3565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166322af10f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156149b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149da919061564d565b90506149e683826157ab565b4211614a6e5760405162461bcd60e51b815260206004820152605e6024820152600080516020615c1883398151915260448201527f6f6e675458735075626c69736865643a206e6f7420656e6f7567682074696d6560648201527f2070617373656420746f20636c61696d20545844617461206973737565730000608482015260a4016105c3565b614a7d8261458e8360016157ab565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630d29fb546040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614ad857600080fd5b505af1158015614aec573d6000803e3d6000fd5b50506040518692507f075b79dc810910e193030673a031c86aae2bcb4d234b560afa42071dbdc0641c9150600090a250505050565b604051631000260b60e21b81526004810183905281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690634000982c90602401602060405180830381865afa158015614b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bac919061564d565b14614c285760405162461bcd60e51b81526020600482015260526024820152600080516020615c1883398151915260448201527f6f6e67556e697665727365526f6f745075626c69736865643a20696e636f72726064820152716563742070726f766964656420766572736560701b608482015260a4016105c3565b604051631465bca160e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906328cb794290602401602060405180830381865afa158015614c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cb19190615632565b614d105760405162461bcd60e51b815260206004820152602a60248201527f6e6f7420726561647920666f722077726f6e67556e697665727365526f6f742060448201526939bab136b4b9b9b4b7b760b11b60648201526084016105c3565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630d29fb546040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614d6b57600080fd5b505af1158015614d7f573d6000803e3d6000fd5b505060408051858152602081018590527f949a8e927046ac72af5dc1efd738f16ac10e5d4cb40277e809e7194c26b68348935001905060405180910390a15050565b6040516306bee10560e01b815260006004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906306bee105906044016020604051808303816000875af1158015614e2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e53919061564d565b50604051632bf660ef60e21b8152600060048201526001600160a01b0383811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063afd983bc90604401600060405180830381600087803b158015614ebe57600080fd5b505af1158015614ed2573d6000803e3d6000fd5b505050505050565b60008060408385031215614eed57600080fd5b50508035926020909101359150565b60008083601f840112614f0e57600080fd5b5081356001600160401b03811115614f2557600080fd5b602083019150836020828501011115614f3d57600080fd5b9250929050565b60008060008060608587031215614f5a57600080fd5b843593506020850135925060408501356001600160401b03811115614f7e57600080fd5b614f8a87828801614efc565b95989497509550505050565b803563ffffffff81168114614faa57600080fd5b919050565b600080600060608486031215614fc457600080fd5b8335925060208401359150614fdb60408501614f96565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561502257615022614fe4565b604052919050565b60006001600160401b0382111561504357615043614fe4565b50601f01601f191660200190565b600082601f83011261506257600080fd5b81356150756150708261502a565b614ffa565b81815284602083860101111561508a57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156150b957600080fd5b81356001600160401b038111156150cf57600080fd5b6150db84828501615051565b949350505050565b6000602082840312156150f557600080fd5b5035919050565b60008060008060008060008060c0898b03121561511857600080fd5b8835975060208901359650604089013595506060890135945060808901356001600160401b038082111561514b57600080fd5b6151578c838d01614efc565b909650945060a08b013591508082111561517057600080fd5b5061517d8b828c01614efc565b999c989b5096995094979396929594505050565b6000806000604084860312156151a657600080fd5b8335925060208401356001600160401b038111156151c357600080fd5b6151cf86828701614efc565b9497909650939450505050565b600080604083850312156151ef57600080fd5b8235915060208301356001600160401b0381111561520c57600080fd5b61521885828601615051565b9150509250929050565b60008060008060008060a0878903121561523b57600080fd5b86359550602087013594506040870135935061525960608801614f96565b925060808701356001600160401b0381111561527457600080fd5b61528089828a01614efc565b979a9699509497509295939492505050565b600082601f8301126152a357600080fd5b813560206001600160401b038211156152be576152be614fe4565b8160051b6152cd828201614ffa565b92835284810182019282810190878511156152e757600080fd5b83870192505b84831015615306578235825291830191908301906152ed565b979650505050505050565b6000806040838503121561532457600080fd5b82356001600160401b0381111561533a57600080fd5b61534685828601615292565b95602094909401359450505050565b6000806000806080858703121561536b57600080fd5b8435935060208501356001600160401b0381111561538857600080fd5b61539487828801615292565b949794965050505060408301359260600135919050565b600080600080600080600060a0888a0312156153c657600080fd5b87359650602088013595506040880135945060608801356001600160401b03808211156153f257600080fd5b6153fe8b838c01614efc565b909650945060808a013591508082111561541757600080fd5b506154248a828b01614efc565b989b979a50959850939692959293505050565b60005b8381101561545257818101518382015260200161543a565b838111156114165750506000910152565b6020815260008251806020840152615482816040850160208701615437565b601f01601f19169190910160400192915050565b6000806000606084860312156154ab57600080fd5b8335925060208401356001600160401b038111156154c857600080fd5b6154d486828701615292565b925050604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561551d57835183529284019291840191600101615501565b50909695505050505050565b60008060006060848603121561553e57600080fd5b83356001600160401b0381111561555457600080fd5b61556086828701615051565b93505060208401359150614fdb60408501614f96565b60ff81168114613a7257600080fd5b6000806000806080858703121561559b57600080fd5b8435935060208501356155ad81615576565b93969395505050506040820135916060013590565b6000602082840312156155d457600080fd5b81516001600160a01b03811681146135ca57600080fd5b6020808252601d908201527f4f6e6c792073757065725573657220697320617574686f72697a65642e000000604082015260600190565b80518015158114614faa57600080fd5b60006020828403121561564457600080fd5b611d8f82615622565b60006020828403121561565f57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561568e5761568e615666565b500390565b60208082526026908201527f4f6e6c792072656c6179206f6620756e6976657273657320697320617574686f6040820152653934bd32b21760d11b606082015260800190565b6020808252602b908201527f7365744e6577556e697665727365526f6f743a20756e69766572736520616c7260408201526a1958591e4818db1bdcd95960aa1b606082015260800190565b6020808252602a908201527f756e69766572736520726f6f7420757064617465207369676e6174757265206e6040820152691bdd0818dbdc9c9958dd60b21b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260006150db60208301848661576e565b600082198211156157be576157be615666565b500190565b600080604083850312156157d657600080fd5b6157df83615622565b915060208301516157ef81615576565b809150509250929050565b60006020828403121561580c57600080fd5b81516135ca81615576565b600181815b8085111561585257816000190482111561583857615838615666565b8085161561584557918102915b93841c939080029061581c565b509250929050565b60008261586957506001611d92565b8161587657506000611d92565b816001811461588c5760028114615896576158b2565b6001915050611d92565b60ff8411156158a7576158a7615666565b50506001821b611d92565b5060208310610133831016604e8410600b84101617156158d5575081810a611d92565b6158df8383615817565b80600019048211156158f3576158f3615666565b029392505050565b6000611d8f838361585a565b84815260ff8416602082015260606040820152600061592a60608301848661576e565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601260045260246000fd5b60008261596f5761596f61594a565b500490565b600081600019048311821515161561598e5761598e615666565b500290565b60006000198214156159a7576159a7615666565b5060010190565b6000826159bd576159bd61594a565b500690565b600060ff821660ff8114156159d9576159d9615666565b60010192915050565b600063ffffffff808316818114156159fc576159fc615666565b6001019392505050565b600060208284031215615a1857600080fd5b81516001600160401b03811115615a2e57600080fd5b8201601f81018413615a3f57600080fd5b8051615a4d6150708261502a565b818152856020838501011115615a6257600080fd5b6127fe826020830160208601615437565b600060ff821660ff84168060ff03821115615a9057615a90615666565b019392505050565b6020808252602d908201527f72657175657374556e697665727365436c6f737572653a207369676e6174757260408201526c19481b9bdd0818dbdc9c9958dd609a1b606082015260800190565b60208082526027908201527f72657175657374556e697665727365436c6f737572653a207265717565737420604082015266195e1c1a5c995960ca1b606082015260800190565b6020808252602f908201527f72657175657374556e697665727365436c6f737572653a20756e69766572736560408201526e08185b1c9958591e4818db1bdcd959608a1b606082015260800190565b600063ffffffff83811690831681811015615b9857615b98615666565b039392505050565b600063ffffffff80841680615bb757615bb761594a565b92169190910492915050565b600063ffffffff80831681851681830481118215151615615be657615be6615666565b02949350505050565b600063ffffffff808316818516808303821115615c0e57615c0e615666565b0194935050505056fe557064617465733a3a5f6d6f7665546f476f7665726e616e636546726f6d5772a2646970667358221220ac51f8ba08aeba87e3804d541fe2cedb44c4727e24990bfa9e2b357d8dd19d6164736f6c634300080b0033000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a226000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c749

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101fa5760003560e01c80638bf82e971161011a578063ce7abcb8116100ad578063dcf4318c1161007c578063dcf4318c146104bd578063e5df669f146104d0578063f0af24e7146104e3578063f47dd9b1146104f6578063f74a6d8b146104fe57600080fd5b8063ce7abcb814610449578063d00920521461045c578063d0ba06f01461046f578063d28757cc1461049657600080fd5b8063a92550ad116100e9578063a92550ad146103dc578063adc72df714610403578063b701017f14610423578063bc0b907d1461043657600080fd5b80638bf82e97146103845780638c9ac90a146103a15780639a95ce05146103b4578063a11c758f146103c757600080fd5b80633033951d116101925780635f4db235116101615780635f4db235146103365780636875c5b9146103495780636b87d24c1461035c5780638b0c66071461037157600080fd5b80633033951d146102be5780633d43a239146102d15780634c04896f146102e45780635f2d1f8d1461032357600080fd5b80631f275713116101ce5780631f2757131461026257806324998252146102755780632c19dfba146102885780632f4e29121461029b57600080fd5b8062d4a20f146101ff5780630f254e9814610214578063186b7bf6146102275780631cff8b101461023a575b600080fd5b61021261020d366004614eda565b610511565b005b610212610222366004614f44565b610afe565b610212610235366004614faf565b610f82565b61024f6102483660046150a7565b6040015190565b6040519081526020015b60405180910390f35b61024f6102703660046150e3565b6115fb565b6102126102833660046150fc565b61164e565b610212610296366004615191565b611c50565b6102ae6102a93660046151dc565b611d71565b6040519015158152602001610259565b61024f6102cc366004614eda565b611d98565b6102126102df366004615222565b611dc3565b61030b7f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a22681565b6040516001600160a01b039091168152602001610259565b61024f610331366004615311565b6123fd565b6102ae610344366004615355565b612760565b6102126103573660046153ab565b612807565b610364612cbe565b6040516102599190615463565b61030b61037f3660046151dc565b612d4b565b61038c600181565b60405163ffffffff9091168152602001610259565b6102126103af3660046150e3565b612e23565b6102126103c2366004614eda565b612f76565b61024f6103d53660046150a7565b6020015190565b61030b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b4381565b610416610411366004615496565b61326e565b60405161025991906154e5565b610212610431366004614f44565b6135d1565b6102126104443660046150e3565b613a5d565b6102126104573660046150e3565b613a75565b61041661046a366004615529565b613d91565b61030b7f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c74981565b6104ab6104a43660046150a7565b6001015190565b60405160ff9091168152602001610259565b6104ab6104cb366004614eda565b613e4b565b61030b6104de366004615585565b613e7d565b6104166104f13660046150a7565b613ee5565b6102ae613f7c565b61021261050c366004614f44565b614000565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663b65c630b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561056f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061059391906155c2565b6001600160a01b0316336001600160a01b0316146105cc5760405162461bcd60e51b81526004016105c3906155eb565b60405180910390fd5b7f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b031663eeab68fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561062a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064e9190615632565b6106d05760405162461bcd60e51b815260206004820152604760248201527f557064617465733a3a62797061737343757272656e74556e697665727365566560448201527f7273653a2073797374656d206e6f74206177616974696e6720666f7220476f7660648201526665726e616e636560c81b608482015260a4016105c3565b604051631000260b60e21b81526004810183905281907f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031690634000982c90602401602060405180830381865afa158015610737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075b919061564d565b146107ce5760405162461bcd60e51b815260206004820152603d60248201527f557064617465733a3a62797061737343757272656e74556e697665727365566560448201527f7273653a20696e636f72726563742070726f766964656420766572736500000060648201526084016105c3565b60006001600160a01b037f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b4316634c552d2e8461080b60018661567c565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa15801561084c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610870919061564d565b905060006001600160a01b037f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43166313efebd4856108af60018761567c565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401602060405180830381865afa1580156108f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610914919061564d565b604051637815415d60e11b8152600481018690529091507f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b03169063f02a82ba906024016020604051808303816000875af115801561097e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a2919061564d565b50604051632383313160e01b81526004810185905260248101839052604481018290527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316906323833131906064016020604051808303816000875af1158015610a18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3c919061564d565b5060405163015e397b60e01b815260048101859052602481018490527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b03169063015e397b90604401600060405180830381600087803b158015610aa657600080fd5b505af1158015610aba573d6000803e3d6000fd5b50505050827fcbb9e9943b702d9e3c8964bfc050c551c571d6fbcb56cb2004ed2c6509c766b385604051610af091815260200190565b60405180910390a250505050565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8091906155c2565b6001600160a01b0316336001600160a01b031614610bb05760405162461bcd60e51b81526004016105c390615693565b60408051606060208201819052601460808301527314995b5bdd9950db1bdcdd5c9954995c5d595cdd60621b60a0830152918101869052908101849052600090610c139060c0015b604051602081830303815290604052805190602001206115fb565b9050610c558184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43169063b4a750b690602401602060405180830381865afa158015610cbe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ce291906155c2565b6001600160a01b031614610d545760405162461bcd60e51b815260206004820152603360248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20736960448201527219db985d1d5c99481b9bdd0818dbdc9c9958dd606a1b60648201526084016105c3565b428411610db95760405162461bcd60e51b815260206004820152602d60248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20726560448201526c1c5d595cdd08195e1c1a5c9959609a1b60648201526084016105c3565b604051635e1d948760e11b8152600481018690527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03169063bc3b290e90602401602060405180830381865afa158015610e1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e429190615632565b15610ead5760405162461bcd60e51b815260206004820152603560248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20756e6044820152741a5d995c9cd948185b1c9958591e4818db1bdcd959605a1b60648201526084016105c3565b604051637983b61d60e11b81526004810186905260006024820181905260448201527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b03169063f3076c3a90606401600060405180830381600087803b158015610f1d57600080fd5b505af1158015610f31573d6000803e3d6000fd5b505060408051888152600060208201819052918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e7925060600190505b60405180910390a15050505050565b63ffffffff8116600114610ffe5760405162461bcd60e51b815260206004820152603a60248201527f557064617465733a3a7375626d69744e65774f776e657273686970526f6f743a60448201527f20696e636f7272656374207478466f726d617456657273696f6e00000000000060648201526084016105c3565b827f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611081919061564d565b146110eb5760405162461bcd60e51b815260206004820152603460248201527f6572726f723a207375626d69744e65774f776e657273686970526f6f7420666f6044820152737220616e20696e636f727265637420766572736560601b60648201526084016105c3565b7f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b0316631624efa96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190615632565b80156112015750604051632bacd5dd60e11b8152600060048201527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031690635759abba90602401602060405180830381865afa1580156111d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111fd919061564d565b8214155b1561141c5760007f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663fed1252a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611266573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128a91906155c2565b604051636f1e853360e01b81523360048201529091506001600160a01b03821690636f1e853390602401602060405180830381865afa1580156112d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f59190615632565b6113605760405162461bcd60e51b815260206004820152603660248201527f557064617465733a3a7375626d69744e65774f776e657273686970526f6f743a604482015275081cdd185ad95c881b9bdd081c9959da5cdd195c995960521b60648201526084016105c3565b7f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316630d29fb546040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156113bb57600080fd5b505af11580156113cf573d6000803e3d6000fd5b50505050837f890c5b8d04c3b93366cc6f7b68f7b2fd236cf9388ac44b15ef0d59336abcf3d08460405161140591815260200190565b60405180910390a26114168461437c565b50505050565b611424613f7c565b6114b15760405162461bcd60e51b815260206004820152605260248201527f6e6f7420726561647920666f72206f776e657273686970207375626d6973736960448201527f6f6e3a207665727365206e6f7420736574746c6564206f72206e657720545873606482015271081b9bdd081cdd589b5a5d1d1959081e595d60721b608482015260a4016105c3565b6040516306bee10560e01b8152600481018390524260248201526000907f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316906306bee105906044016020604051808303816000875af1158015611521573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611545919061564d565b604051632bf660ef60e21b8152600060048201523360248201529091507f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b03169063afd983bc90604401600060405180830381600087803b1580156115b057600080fd5b505af11580156115c4573d6000803e3d6000fd5b50506040518392508591507faf90c4aa6579d46f1d1728fd0113c96d153d42aaa5ab1f5bc241a05c4fc622af90600090a350505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d091906155c2565b6001600160a01b0316336001600160a01b0316146117005760405162461bcd60e51b81526004016105c390615693565b604051635e1d948760e11b8152600481018890527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03169063bc3b290e90602401602060405180830381865afa158015611765573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117899190615632565b156117a65760405162461bcd60e51b81526004016105c3906156d9565b60405163249f9e7360e11b8152600481018890527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03169063493f3ce690602401602060405180830381865afa15801561180b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182f919061564d565b851461187d5760405162461bcd60e51b815260206004820152601c60248201527f707265765472616e73526f6f7420646f6573206e6f74206d617463680000000060448201526064016105c3565b60405163666beda160e01b8152600481018890527f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b03169063666beda190602401602060405180830381865afa1580156118e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119069190615632565b6119785760405162461bcd60e51b815260206004820152603960248201527f6e6f7420726561647920666f7220756e69766572736520726f6f74207375626d60448201527f697373696f6e3a207665727365206e6f7420736574746c65640000000000000060648201526084016105c3565b60405163213f03fb60e21b8152600481018890527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316906384fc0fec90602401602060405180830381865afa1580156119dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a019190615632565b611b1d576000611a268787604051602001610bf8929190918252602082015260400190565b9050611a688186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018a90526001600160a01b03918216917f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43169063b4a750b690602401602060405180830381865afa158015611ad1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af591906155c2565b6001600160a01b031614611b1b5760405162461bcd60e51b81526004016105c390615724565b505b604051632383313160e01b815260048101889052602481018790524260448201526000907f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316906323833131906064016020604051808303816000875af1158015611b94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb8919061564d565b9050808914611c095760405162461bcd60e51b815260206004820152601f60248201527f6572726f723a20696e636f727265637420756e6976657273652076657273650060448201526064016105c3565b8087897f3622597e9085739b48cf129e1f6dfb4cb8c29aa6bccc1d92bc07791eb2fd19888686604051611c3d929190615797565b60405180910390a4505050505050505050565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663aba3e1116040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd291906155c2565b6001600160a01b0316336001600160a01b031614611d325760405162461bcd60e51b815260206004820181905260248201527f4f6e6c792072656c6179206f662054587320697320617574686f72697a65642e60448201526064016105c3565b827ff09c0c2e1067d84ab49d3bff959e45870f3417b16c65199accc451bca46e0d508383604051611d64929190615797565b60405180910390a2505050565b6000611d8f83611d8084613ee5565b60408501516020860151612760565b90505b92915050565b600081158015611da6575082155b15611db357506000611d92565b5060009182526020526040902090565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663aba3e1116040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4591906155c2565b6001600160a01b0316336001600160a01b031614611ea55760405162461bcd60e51b815260206004820181905260248201527f4f6e6c792072656c6179206f662054587320697320617574686f72697a65642e60448201526064016105c3565b63ffffffff8316600114611f185760405162461bcd60e51b815260206004820152603460248201527f557064617465733a3a7375626d69744e6577545873526f6f743a20696e636f726044820152733932b1ba103a3c2337b936b0ba2b32b939b4b7b760611b60648201526084016105c3565b857f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9b919061564d565b611fa69060016157ab565b1461200a5760405162461bcd60e51b815260206004820152602e60248201527f6572726f723a207375626d69744e6577545873526f6f7420666f7220616e206960448201526d6e636f727265637420766572736560901b60648201526084016105c3565b6000807f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b031663ad71247e6040518163ffffffff1660e01b81526004016040805180830381865afa15801561206a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061208e91906157c3565b91509150816121055760405162461bcd60e51b815260206004820152603860248201527f6e6f7420726561647920746f20616363657074206e6577205458207375626d6960448201527f7373696f6e2c207665727365206e6f7420736574746c6564000000000000000060648201526084016105c3565b8060ff166001148061211a57508060ff166002145b61217e5760405162461bcd60e51b815260206004820152602f60248201527f7061737420766572736520656e64656420757020736574746c696e6720696e2060448201526e1a5b98dbdc9c9958dd081b195d995b608a1b60648201526084016105c3565b856121e95786156121e95760405162461bcd60e51b815260206004820152602f60248201527f696e20612076657273652077697468206e6f205458732c20746865205458526f60448201526e1bdd081b5d5cdd081899481b9d5b1b608a1b60648201526084016105c3565b60007f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663456c405a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612249573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226d91906157fa565b90506000612283886104cb60ff851660026158fb565b6040516323da0e0960e21b8152600481018b9052426024820152604481018a905260ff8086166064830152821660848201529091506000906001600160a01b037f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2261690638f6838249060a4016020604051808303816000875af115801561230e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612332919061564d565b905060018111156123b1577f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316634bb278f36040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561239857600080fd5b505af11580156123ac573d6000803e3d6000fd5b505050505b808a7f6f3984a8056b744a2405c513c3027efbcc8f00fb16be25a2e3fb772238b3455d8b868b8b6040516123e89493929190615907565b60405180910390a35050505050505050505050565b600081612426578260008151811061241757612417615934565b60200260200101519050611d92565b60006124338360026158fb565b905083518110156124ac5760405162461bcd60e51b815260206004820152603860248201527f6d65726b6c65526f6f743a206e6f7420656e6f756768206c6576656c7320676960448201527f76656e20746865206e756d626572206f66206c6561766573000000000000000060648201526084016105c3565b6124b7600282615960565b90506000816001600160401b038111156124d3576124d3614fe4565b6040519080825280602002602001820160405280156124fc578160200160208202803683370190505b50905060006002865161250f9190615960565b905060005b818110156125a8576125798761252b836002615974565b8151811061253b5761253b615934565b6020026020010151888360026125519190615974565b61255c9060016157ab565b8151811061256c5761256c615934565b6020026020010151611d98565b83828151811061258b5761258b615934565b6020908102919091010152806125a081615993565b915050612514565b50600286516125b791906159ae565b1561261a576125ef86600188516125ce919061567c565b815181106125de576125de615934565b60200260200101516000801b611d98565b82828151811061260157612601615934565b60209081029190910101526126176001826157ab565b90505b60015b858160ff16101561273957612633600285615960565b93506126406002836159ae565b1561266057612650600283615960565b61265b9060016157ab565b61266b565b61266b600283615960565b915083821115612679578391505b60005b828110156126e8576126b984612693836002615974565b815181106126a3576126a3615934565b6020026020010151858360026125519190615974565b8482815181106126cb576126cb615934565b6020908102919091010152806126e081615993565b91505061267c565b50815b84811015612726576000801b84828151811061270957612709615934565b60209081029190910101528061271e81615993565b9150506126eb565b5080612731816159c2565b91505061261d565b508160008151811061274d5761274d615934565b6020026020010151935050505092915050565b6000805b84518163ffffffff1610156127f05761277e6002846159ae565b6127a55761279e84868363ffffffff168151811061256c5761256c615934565b93506127d1565b6127ce858263ffffffff16815181106127c0576127c0615934565b602002602001015185611d98565b93505b6127dc600284615960565b9250806127e8816159e2565b915050612764565b50811580156127fe57508285145b95945050505050565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612865573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288991906155c2565b6001600160a01b0316336001600160a01b0316146128b95760405162461bcd60e51b81526004016105c390615693565b604051635e1d948760e11b8152600481018890527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03169063bc3b290e90602401602060405180830381865afa15801561291e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129429190615632565b1561295f5760405162461bcd60e51b81526004016105c3906156d9565b60405163249f9e7360e11b8152600481018890527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03169063493f3ce690602401602060405180830381865afa1580156129c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e8919061564d565b8514612a365760405162461bcd60e51b815260206004820152601c60248201527f707265765472616e73526f6f7420646f6573206e6f74206d617463680000000060448201526064016105c3565b60405163213f03fb60e21b8152600481018890527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316906384fc0fec90602401602060405180830381865afa158015612a9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612abf9190615632565b612bdb576000612ae48787604051602001610bf8929190918252602082015260400190565b9050612b268186868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018a90526001600160a01b03918216917f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43169063b4a750b690602401602060405180830381865afa158015612b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bb391906155c2565b6001600160a01b031614612bd95760405162461bcd60e51b81526004016105c390615724565b505b604051632383313160e01b815260048101889052602481018790524260448201526000907f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316906323833131906064016020604051808303816000875af1158015612c52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c76919061564d565b90508087897f3622597e9085739b48cf129e1f6dfb4cb8c29aa6bccc1d92bc07791eb2fd19888686604051612cac929190615797565b60405180910390a45050505050505050565b60607f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316636b87d24c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612d1e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612d469190810190615a06565b905090565b6000806000808451604114612d665760009350505050611d92565b50505060208201516040830151604184015160ff16601b811015612d9257612d8f601b82615a73565b90505b8060ff16601b14158015612daa57508060ff16601c14155b15612dbb5760009350505050611d92565b60408051600081526020810180835288905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015612e0e573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663b65c630b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ea591906155c2565b6001600160a01b0316336001600160a01b031614612ed55760405162461bcd60e51b81526004016105c3906155eb565b60007f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316630738ccce6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f59919061564d565b90506000612f68838383614758565b612f718361437c565b505050565b60007f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663fed1252a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffa91906155c2565b604051636f1e853360e01b81523360048201529091506001600160a01b03821690636f1e853390602401602060405180830381865afa158015613041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130659190615632565b6130c45760405162461bcd60e51b815260206004820152602a60248201527f6f6e6c79207374616b65722063616e207265706f72742077726f6e6720756e696044820152691d995c9cd9481c9bdbdd60b21b60648201526084016105c3565b7f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b031663f47dd9b16040518163ffffffff1660e01b8152600401602060405180830381865afa158015613122573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131469190615632565b806131ce57507f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b0316631624efa96040518163ffffffff1660e01b8152600401602060405180830381865afa1580156131aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ce9190615632565b156132645760007f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613233573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613257919061564d565b90506132628161437c565b505b612f718383614b21565b60608161335a5782516001146132e15760405162461bcd60e51b815260206004820152603260248201527f6275696c6450726f6f663a206c6561766573206c656e677468206d75737420626044820152710652030206966206e4c6576656c73203d20360741b60648201526084016105c3565b83156133555760405162461bcd60e51b815260206004820152603760248201527f6275696c6450726f6f663a206c656166506f73206d757374206265203020696660448201527f207468657265206973206f6e6c79206f6e65206c65616600000000000000000060648201526084016105c3565b6135ca565b60006133678360026158fb565b9050808451146133ca5760405162461bcd60e51b815260206004820152602860248201527f6e756d626572206f66206c6561766573206973206e6f74203d20706f7728322c6044820152676e4c6576656c732960c01b60648201526084016105c3565b826001600160401b038111156133e2576133e2614fe4565b60405190808252806020026020018201604052801561340b578160200160208202803683370190505b5091506134196002866159ae565b15613447578361342a60018761567c565b8151811061343a5761343a615934565b602002602001015161346c565b836134538660016157ab565b8151811061346357613463615934565b60200260200101515b8260008151811061347f5761347f615934565b60200260200101818152505060005b61349960018561567c565b8160ff1610156135c7576134ae600283615960565b91506134bb600287615960565b955060005b8281101561352c576134fd866134d7836002615974565b815181106134e7576134e7615934565b6020026020010151878360026125519190615974565b86828151811061350f5761350f615934565b60209081029190910101528061352481615993565b9150506134c0565b506135386002876159ae565b15613566578461354960018861567c565b8151811061355957613559615934565b602002602001015161358b565b846135728760016157ab565b8151811061358257613582615934565b60200260200101515b83613597836001615a73565b60ff16815181106135aa576135aa615934565b6020908102919091010152806135bf816159c2565b91505061348e565b50505b9392505050565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561362f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061365391906155c2565b6001600160a01b0316336001600160a01b0316146136835760405162461bcd60e51b81526004016105c390615693565b60408051606060208201819052600e60808301526d436f6e6669726d436c6f7375726560901b60a08301529181018690529081018490526000906136c99060c001610bf8565b905061370b8184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43169063b4a750b690602401602060405180830381865afa158015613774573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061379891906155c2565b6001600160a01b0316146137be5760405162461bcd60e51b81526004016105c390615a98565b4284116137dd5760405162461bcd60e51b81526004016105c390615ae5565b604051635e1d948760e11b8152600481018690527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03169063bc3b290e90602401602060405180830381865afa158015613842573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138669190615632565b156138835760405162461bcd60e51b81526004016105c390615b2c565b6040516395592de760e01b8152600481018690527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316906395592de790602401602060405180830381865afa1580156138e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061390c9190615632565b6139935760405162461bcd60e51b815260206004820152604c60248201527f72657175657374556e697665727365436c6f737572653a20756e69766572736560448201527f20636c6f73757265206d75737420626520726571756573746564206265666f7260648201526b6520636f6e6669726d696e6760a01b608482015260a4016105c3565b604051637983b61d60e11b81526004810186905260016024820181905260448201527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b03169063f3076c3a90606401600060405180830381600087803b158015613a0357600080fd5b505af1158015613a17573d6000803e3d6000fd5b505060408051888152600160208201819052918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e792506060019050610f73565b613a6981600033614758565b613a728161437c565b50565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663b65c630b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af791906155c2565b6001600160a01b0316336001600160a01b031614613b275760405162461bcd60e51b81526004016105c3906155eb565b7f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b031663eeab68fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ba99190615632565b613c255760405162461bcd60e51b815260206004820152604160248201527f557064617465733a3a64656163746976617465476f7665726e616e63653a207360448201527f797374656d206e6f74206177616974696e6720666f7220476f7665726e616e636064820152606560f81b608482015260a4016105c3565b807f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ca8919061564d565b14613d1b5760405162461bcd60e51b815260206004820152603760248201527f557064617465733a3a64656163746976617465476f7665726e616e63653a206960448201527f6e636f72726563742070726f766964656420766572736500000000000000000060648201526084016105c3565b7f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b031663baebc7986040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613d7657600080fd5b505af1158015613d8a573d6000803e3d6000fd5b5050505050565b606060008263ffffffff166001600160401b03811115613db357613db3614fe4565b604051908082528060200260200182016040528015613ddc578160200160208202803683370190505b50905060005b8363ffffffff168163ffffffff161015613e4257613e016020866157ab565b9450600085870151905080838363ffffffff1681518110613e2457613e24615934565b60209081029190910101525080613e3a816159e2565b915050613de2565b50949350505050565b6003815b80841115613e765781613e61816159c2565b9250613e6f90508382615974565b9050613e4f565b5092915050565b6040805160008082526020820180845287905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa158015613ed1573d6000803e3d6000fd5b5050604051601f1901519695505050505050565b60606000602060408451613ef99190615b7b565b613f039190615ba0565b9050613f10816020615bc3565b613f1b906040615bef565b63ffffffff16835114613f705760405162461bcd60e51b815260206004820152601b60248201527f696e636f72726563742073657269616c697a6564206c656e677468000000000060448201526064016105c3565b6135ca83604083613d91565b60007f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b031663f47dd9b16040518163ffffffff1660e01b8152600401602060405180830381865afa158015613fdc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d469190615632565b7f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561405e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061408291906155c2565b6001600160a01b0316336001600160a01b0316146140b25760405162461bcd60e51b81526004016105c390615693565b60408051606060208201819052600e60808301526d52657175657374436c6f7375726560901b60a08301529181018690529081018490526000906140f89060c001610bf8565b905061413a8184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d4b92505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43169063b4a750b690602401602060405180830381865afa1580156141a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141c791906155c2565b6001600160a01b0316146141ed5760405162461bcd60e51b81526004016105c390615a98565b42841161420c5760405162461bcd60e51b81526004016105c390615ae5565b604051635e1d948760e11b8152600481018690527f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03169063bc3b290e90602401602060405180830381865afa158015614271573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142959190615632565b156142b25760405162461bcd60e51b81526004016105c390615b2c565b604051637983b61d60e11b81526004810186905260016024820152600060448201527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b03169063f3076c3a90606401600060405180830381600087803b15801561432257600080fd5b505af1158015614336573d6000803e3d6000fd5b505060408051888152600160208201526000918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e792506060019050610f73565b807f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156143db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143ff919061564d565b1461446b5760405162461bcd60e51b815260206004820152603660248201527f557064617465733a3a5f62797061737343757272656e7456657273653a20696e604482015275636f72726563742070726f766964656420766572736560501b60648201526084016105c3565b60007f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031663657aea9f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156144cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144ef919061564d565b8214905080614596576000807f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03166322af10f46040518163ffffffff1660e01b8152600401602060405180830381865afa158015614559573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061457d919061564d565b90506145938261458e8360016157ab565b614dc1565b50505b60006001600160a01b037f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b431663fd5a64996145d260018661567c565b6040518263ffffffff1660e01b81526004016145f091815260200190565b602060405180830381865afa15801561460d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614631919061564d565b6040516375da387560e01b8152600481018290529091507f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316906375da387590602401600060405180830381600087803b15801561469657600080fd5b505af11580156146aa573d6000803e3d6000fd5b505060405163e889d33760e01b8152600481018690527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316925063e889d3379150602401600060405180830381600087803b15801561471057600080fd5b505af1158015614724573d6000803e3d6000fd5b50506040518592507fcfa8dd9c1dd3c45573e593c8000f407cbeb29fcd04a9bd1e17a8af27db1391469150600090a2505050565b7f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b031663f47dd9b16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147da9190615632565b6148605760405162461bcd60e51b815260206004820152605d6024820152600080516020615c1883398151915260448201527f6f6e675458735075626c69736865643a2073797374656d206e6f74206177616960648201527f74696e6720666f72206f776e657273686970207375626d697373696f6e000000608482015260a4016105c3565b827f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148e3919061564d565b146149565760405162461bcd60e51b81526020600482015260496024820152600080516020615c1883398151915260448201527f6f6e675458735075626c69736865643a20696e636f72726563742070726f766960648201526864656420766572736560b81b608482015260a4016105c3565b60007f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b03166322af10f46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156149b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149da919061564d565b90506149e683826157ab565b4211614a6e5760405162461bcd60e51b815260206004820152605e6024820152600080516020615c1883398151915260448201527f6f6e675458735075626c69736865643a206e6f7420656e6f7567682074696d6560648201527f2070617373656420746f20636c61696d20545844617461206973737565730000608482015260a4016105c3565b614a7d8261458e8360016157ab565b7f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316630d29fb546040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614ad857600080fd5b505af1158015614aec573d6000803e3d6000fd5b50506040518692507f075b79dc810910e193030673a031c86aae2bcb4d234b560afa42071dbdc0641c9150600090a250505050565b604051631000260b60e21b81526004810183905281907f000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b436001600160a01b031690634000982c90602401602060405180830381865afa158015614b88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614bac919061564d565b14614c285760405162461bcd60e51b81526020600482015260526024820152600080516020615c1883398151915260448201527f6f6e67556e697665727365526f6f745075626c69736865643a20696e636f72726064820152716563742070726f766964656420766572736560701b608482015260a4016105c3565b604051631465bca160e11b8152600481018390527f000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c7496001600160a01b0316906328cb794290602401602060405180830381865afa158015614c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cb19190615632565b614d105760405162461bcd60e51b815260206004820152602a60248201527f6e6f7420726561647920666f722077726f6e67556e697665727365526f6f742060448201526939bab136b4b9b9b4b7b760b11b60648201526084016105c3565b7f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316630d29fb546040518163ffffffff1660e01b8152600401600060405180830381600087803b158015614d6b57600080fd5b505af1158015614d7f573d6000803e3d6000fd5b505060408051858152602081018590527f949a8e927046ac72af5dc1efd738f16ac10e5d4cb40277e809e7194c26b68348935001905060405180910390a15050565b6040516306bee10560e01b815260006004820152602481018290527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a2266001600160a01b0316906306bee105906044016020604051808303816000875af1158015614e2f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e53919061564d565b50604051632bf660ef60e21b8152600060048201526001600160a01b0383811660248301527f000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a226169063afd983bc90604401600060405180830381600087803b158015614ebe57600080fd5b505af1158015614ed2573d6000803e3d6000fd5b505050505050565b60008060408385031215614eed57600080fd5b50508035926020909101359150565b60008083601f840112614f0e57600080fd5b5081356001600160401b03811115614f2557600080fd5b602083019150836020828501011115614f3d57600080fd5b9250929050565b60008060008060608587031215614f5a57600080fd5b843593506020850135925060408501356001600160401b03811115614f7e57600080fd5b614f8a87828801614efc565b95989497509550505050565b803563ffffffff81168114614faa57600080fd5b919050565b600080600060608486031215614fc457600080fd5b8335925060208401359150614fdb60408501614f96565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561502257615022614fe4565b604052919050565b60006001600160401b0382111561504357615043614fe4565b50601f01601f191660200190565b600082601f83011261506257600080fd5b81356150756150708261502a565b614ffa565b81815284602083860101111561508a57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156150b957600080fd5b81356001600160401b038111156150cf57600080fd5b6150db84828501615051565b949350505050565b6000602082840312156150f557600080fd5b5035919050565b60008060008060008060008060c0898b03121561511857600080fd5b8835975060208901359650604089013595506060890135945060808901356001600160401b038082111561514b57600080fd5b6151578c838d01614efc565b909650945060a08b013591508082111561517057600080fd5b5061517d8b828c01614efc565b999c989b5096995094979396929594505050565b6000806000604084860312156151a657600080fd5b8335925060208401356001600160401b038111156151c357600080fd5b6151cf86828701614efc565b9497909650939450505050565b600080604083850312156151ef57600080fd5b8235915060208301356001600160401b0381111561520c57600080fd5b61521885828601615051565b9150509250929050565b60008060008060008060a0878903121561523b57600080fd5b86359550602087013594506040870135935061525960608801614f96565b925060808701356001600160401b0381111561527457600080fd5b61528089828a01614efc565b979a9699509497509295939492505050565b600082601f8301126152a357600080fd5b813560206001600160401b038211156152be576152be614fe4565b8160051b6152cd828201614ffa565b92835284810182019282810190878511156152e757600080fd5b83870192505b84831015615306578235825291830191908301906152ed565b979650505050505050565b6000806040838503121561532457600080fd5b82356001600160401b0381111561533a57600080fd5b61534685828601615292565b95602094909401359450505050565b6000806000806080858703121561536b57600080fd5b8435935060208501356001600160401b0381111561538857600080fd5b61539487828801615292565b949794965050505060408301359260600135919050565b600080600080600080600060a0888a0312156153c657600080fd5b87359650602088013595506040880135945060608801356001600160401b03808211156153f257600080fd5b6153fe8b838c01614efc565b909650945060808a013591508082111561541757600080fd5b506154248a828b01614efc565b989b979a50959850939692959293505050565b60005b8381101561545257818101518382015260200161543a565b838111156114165750506000910152565b6020815260008251806020840152615482816040850160208701615437565b601f01601f19169190910160400192915050565b6000806000606084860312156154ab57600080fd5b8335925060208401356001600160401b038111156154c857600080fd5b6154d486828701615292565b925050604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b8181101561551d57835183529284019291840191600101615501565b50909695505050505050565b60008060006060848603121561553e57600080fd5b83356001600160401b0381111561555457600080fd5b61556086828701615051565b93505060208401359150614fdb60408501614f96565b60ff81168114613a7257600080fd5b6000806000806080858703121561559b57600080fd5b8435935060208501356155ad81615576565b93969395505050506040820135916060013590565b6000602082840312156155d457600080fd5b81516001600160a01b03811681146135ca57600080fd5b6020808252601d908201527f4f6e6c792073757065725573657220697320617574686f72697a65642e000000604082015260600190565b80518015158114614faa57600080fd5b60006020828403121561564457600080fd5b611d8f82615622565b60006020828403121561565f57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008282101561568e5761568e615666565b500390565b60208082526026908201527f4f6e6c792072656c6179206f6620756e6976657273657320697320617574686f6040820152653934bd32b21760d11b606082015260800190565b6020808252602b908201527f7365744e6577556e697665727365526f6f743a20756e69766572736520616c7260408201526a1958591e4818db1bdcd95960aa1b606082015260800190565b6020808252602a908201527f756e69766572736520726f6f7420757064617465207369676e6174757265206e6040820152691bdd0818dbdc9c9958dd60b21b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260006150db60208301848661576e565b600082198211156157be576157be615666565b500190565b600080604083850312156157d657600080fd5b6157df83615622565b915060208301516157ef81615576565b809150509250929050565b60006020828403121561580c57600080fd5b81516135ca81615576565b600181815b8085111561585257816000190482111561583857615838615666565b8085161561584557918102915b93841c939080029061581c565b509250929050565b60008261586957506001611d92565b8161587657506000611d92565b816001811461588c5760028114615896576158b2565b6001915050611d92565b60ff8411156158a7576158a7615666565b50506001821b611d92565b5060208310610133831016604e8410600b84101617156158d5575081810a611d92565b6158df8383615817565b80600019048211156158f3576158f3615666565b029392505050565b6000611d8f838361585a565b84815260ff8416602082015260606040820152600061592a60608301848661576e565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601260045260246000fd5b60008261596f5761596f61594a565b500490565b600081600019048311821515161561598e5761598e615666565b500290565b60006000198214156159a7576159a7615666565b5060010190565b6000826159bd576159bd61594a565b500690565b600060ff821660ff8114156159d9576159d9615666565b60010192915050565b600063ffffffff808316818114156159fc576159fc615666565b6001019392505050565b600060208284031215615a1857600080fd5b81516001600160401b03811115615a2e57600080fd5b8201601f81018413615a3f57600080fd5b8051615a4d6150708261502a565b818152856020838501011115615a6257600080fd5b6127fe826020830160208601615437565b600060ff821660ff84168060ff03821115615a9057615a90615666565b019392505050565b6020808252602d908201527f72657175657374556e697665727365436c6f737572653a207369676e6174757260408201526c19481b9bdd0818dbdc9c9958dd609a1b606082015260800190565b60208082526027908201527f72657175657374556e697665727365436c6f737572653a207265717565737420604082015266195e1c1a5c995960ca1b606082015260800190565b6020808252602f908201527f72657175657374556e697665727365436c6f737572653a20756e69766572736560408201526e08185b1c9958591e4818db1bdcd959608a1b606082015260800190565b600063ffffffff83811690831681811015615b9857615b98615666565b039392505050565b600063ffffffff80841680615bb757615bb761594a565b92169190910492915050565b600063ffffffff80831681851681830481118215151615615be657615be6615666565b02949350505050565b600063ffffffff808316818516808303821115615c0e57615c0e615666565b0194935050505056fe557064617465733a3a5f6d6f7665546f476f7665726e616e636546726f6d5772a2646970667358221220ac51f8ba08aeba87e3804d541fe2cedb44c4727e24990bfa9e2b357d8dd19d6164736f6c634300080b0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a226000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c749

-----Decoded View---------------
Arg [0] : storageAddress (address): 0xe02b1d70cC1AB07e176ffC35FDb28C8531e08B43
Arg [1] : writer (address): 0xb51EF071Cd21A0A5b1CF588708a1DD8A6554A226
Arg [2] : info (address): 0xA2eFdd8A117A2B125A0b986243ee434Cd831C749

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000e02b1d70cc1ab07e176ffc35fdb28c8531e08b43
Arg [1] : 000000000000000000000000b51ef071cd21a0a5b1cf588708a1dd8a6554a226
Arg [2] : 000000000000000000000000a2efdd8a117a2b125a0b986243ee434cd831c749


Block Transaction 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  ]

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.