Mumbai Testnet

Contract

0xa555533a833D4c6e357E8f48D49ce48ddDdfdf07

Overview

MATIC Balance

Token Holdings

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Value
Submit New Owner...307356492023-01-09 10:32:45523 days ago1673260365IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000003
Submit New T Xs ...307355742023-01-09 10:30:05523 days ago1673260205IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307352282023-01-09 10:17:49523 days ago1673259469IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307351512023-01-09 10:15:05523 days ago1673259305IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307348032023-01-09 10:02:47523 days ago1673258567IN
0xa555533a...ddDdfdf07
0 MATIC0.000332171.65000002
Submit New T Xs ...307347282023-01-09 10:00:07523 days ago1673258407IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307343802023-01-09 9:47:47523 days ago1673257667IN
0xa555533a...ddDdfdf07
0 MATIC0.00032221.60050001
Submit New T Xs ...307343052023-01-09 9:45:09523 days ago1673257509IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307339572023-01-09 9:32:49523 days ago1673256769IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307338812023-01-09 9:30:07523 days ago1673256607IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307335352023-01-09 9:17:51523 days ago1673255871IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307334572023-01-09 9:15:07523 days ago1673255707IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307331092023-01-09 9:02:47523 days ago1673254967IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307330342023-01-09 9:00:07523 days ago1673254807IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307326882023-01-09 8:47:53523 days ago1673254073IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307326112023-01-09 8:45:09523 days ago1673253909IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307322662023-01-09 8:32:55523 days ago1673253175IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307321882023-01-09 8:30:09523 days ago1673253009IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307318382023-01-09 8:17:45523 days ago1673252265IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307317622023-01-09 8:15:05523 days ago1673252105IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307314142023-01-09 8:02:45523 days ago1673251365IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307313392023-01-09 8:00:05523 days ago1673251205IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307309912023-01-09 7:47:45523 days ago1673250465IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
Submit New T Xs ...307309152023-01-09 7:45:05523 days ago1673250305IN
0xa555533a...ddDdfdf07
0 MATIC0.000315791.50000001
Submit New Owner...307305702023-01-09 7:32:51523 days ago1673249571IN
0xa555533a...ddDdfdf07
0 MATIC0.000301971.50000001
View all transactions

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

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x16B90b34...8E2241Ed1
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
Updates

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 12 : 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 "../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
    ) {
        _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"
        );
        // 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);
    }

    // @dev Function left for backwards compatibility only.
    // @dev Will be deprecated in next versions.
    function submitNewTXsRoot(
        uint256 verse,
        bytes32 txRoot,
        uint256 nTXs,
        string calldata ipfsCid
    ) external {
        require(false, "Updates::submitNewTXsRoot: method not supported anymore");
        _dummy = true;
    }

    /**
     * @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);
    }

    // @dev Function left for backwards compatibility only.
    // @dev Will be deprecated in next versions.
    function submitNewOwnershipRoot(uint256 verse, bytes32 ownershipRoot) external {
        require(false, "Updates::submitNewOwnershipRoot: method not supported anymore");
        _dummy = true;
    }

    /// @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"
        );
        require(
            isReadyForOwnershipSubmission(),
            "not ready for ownership submission: verse not settled or new TXs not submitted yet"
        );
        if (IStorageGetters(_sto).nTXsCurrent() == 0) {
            require(
                ownershipRoot == IStorageGetters(_sto).ownershipRootCurrent(),
                "in a verse with no TXs, ownership root should remain the same"
            );
        }
        uint256 ownVerse = IWriter(_writer).addOwnershipRoot(ownershipRoot);
        IWriter(_writer).addChallenge(0, msg.sender); // this guarantees that only a staker could have done this submission
        emit NewOwnershipRoot(ownershipRoot, ownVerse);
    }

    /**
     * @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) {
        (, uint8 actualLevel, ) = IInfo(_info).getCurrentChallengeStatus();
        return (actualLevel == 0);
    }

    /// @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 12 : 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 2 of 12 : 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 2 of 12 : 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 2 of 12 : 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 2 of 12 : 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 2 of 12 : 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 2 of 12 : 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
     * @return ownVerse The length of the ownership array after the addition
     */
    function addOwnershipRoot(bytes32 ownershipRoot)
        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;
}

File 2 of 12 : 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);

    /**
     * @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 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 2 of 12 : 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 2 of 12 : 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";

interface IInfo is IChallengeLibStatus {
    /**
     * @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 isInChallengeOver 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 isInChallengeOver,
            uint8 actualLevel,
            uint256 txVerse
        );

    /**
     * @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 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 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 2 of 12 : 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 nTXs,
        uint256 txRootsCurrentVerse,
        uint256 ownershipSubmissionTimeCurrent,
        uint256 challengeWindowCurrent,
        uint256 txSubmissionTimeCurrent,
        uint256 blockTimestamp,
        uint8 challengesLevel
    ) external pure returns (bool isInChallengeOver, 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 nTXs,
        uint256 currentTime,
        uint256 lastTxSubmissionTime,
        uint256 lastChallTime,
        uint256 challengeWindow,
        uint8 writtenLevel
    )
        external
        pure
        returns (
            bool isSettled,
            uint8 actualLevel,
            uint8 nJumps
        );
}

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

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":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":false,"internalType":"uint32","name":"version","type":"uint32"}],"name":"OwnershipTxFormatVersion","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"},{"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":"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":"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":"ownershipRoot","type":"bytes32"}],"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":"bytes32","name":"txRoot","type":"bytes32"},{"internalType":"uint256","name":"nTXs","type":"uint256"},{"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"}]

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101da5760003560e01c80638b0c660711610104578063d0ba06f0116100a2578063e5df669f11610071578063e5df669f14610477578063f0af24e71461048a578063f47dd9b11461049d578063f74a6d8b146104a557600080fd5b8063d0ba06f014610403578063d196750f1461042a578063d28757cc1461043d578063dcf4318c1461046457600080fd5b8063a92550ad116100de578063a92550ad14610396578063adc72df7146103bd578063b701017f146103dd578063d0092052146103f057600080fd5b80638b0c6607146103515780638bf82e9714610364578063a11c758f1461038157600080fd5b80633033951d1161017c5780635f2d1f8d1161014b5780635f2d1f8d146103035780635f4db235146103165780636875c5b9146103295780636b87d24c1461033c57600080fd5b80633033951d1461028b5780633d43a2391461029e5780634c04896f146102b15780635ece66bf146102f057600080fd5b80631f275713116101b85780631f2757131461022f57806324998252146102425780632c19dfba146102555780632f4e29121461026857600080fd5b80630f254e98146101df578063186b7bf6146101f45780631cff8b1014610207575b600080fd5b6101f26101ed36600461343b565b6104b8565b005b6101f26102023660046134a6565b610945565b61021c61021536600461359e565b6040015190565b6040519081526020015b60405180910390f35b61021c61023d3660046135da565b610e03565b6101f26102503660046135f3565b610e56565b6101f2610263366004613688565b61135d565b61027b6102763660046136d3565b61147e565b6040519015158152602001610226565b61021c610299366004613719565b6114a5565b6101f26102ac36600461373b565b6114d0565b6102d87f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b981565b6040516001600160a01b039091168152602001610226565b6101f26102fe366004613719565b611b0a565b61021c61031136600461382a565b611b78565b61027b61032436600461386e565b611edb565b6101f26103373660046138c4565b611f82565b610344612439565b6040516102269190613980565b6102d861035f3660046136d3565b6124c6565b61036c600181565b60405163ffffffff9091168152602001610226565b61021c61038f36600461359e565b6020015190565b6102d87f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a6681565b6103d06103cb3660046139b3565b61259e565b6040516102269190613a02565b6101f26103eb36600461343b565b612901565b6103d06103fe366004613a46565b612d8d565b6102d87f000000000000000000000000b383f452bb92a6b6d6e73f2edaa4d1f37685a58581565b6101f2610438366004613a93565b612e47565b61045261044b36600461359e565b6001015190565b60405160ff9091168152602001610226565b610452610472366004613719565b612eb5565b6102d8610485366004613b05565b612ee7565b6103d061049836600461359e565b612f4f565b61027b612fe6565b6101f26104b336600461343b565b613077565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053a9190613b42565b6001600160a01b0316336001600160a01b0316146105735760405162461bcd60e51b815260040161056a90613b6b565b60405180910390fd5b60408051606060208201819052601460808301527314995b5bdd9950db1bdcdd5c9954995c5d595cdd60621b60a08301529181018690529081018490526000906105d69060c0015b60405160208183030381529060405280519060200120610e03565b90506106188184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124c692505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a66169063b4a750b690602401602060405180830381865afa158015610681573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a59190613b42565b6001600160a01b0316146107175760405162461bcd60e51b815260206004820152603360248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20736960448201527219db985d1d5c99481b9bdd0818dbdc9c9958dd606a1b606482015260840161056a565b42841161077c5760405162461bcd60e51b815260206004820152602d60248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20726560448201526c1c5d595cdd08195e1c1a5c9959609a1b606482015260840161056a565b604051635e1d948760e11b8152600481018690527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03169063bc3b290e90602401602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108059190613bc1565b156108705760405162461bcd60e51b815260206004820152603560248201527f72656d6f7665556e697665727365436c6f73757265526571756573743a20756e6044820152741a5d995c9cd948185b1c9958591e4818db1bdcd959605a1b606482015260840161056a565b604051637983b61d60e11b81526004810186905260006024820181905260448201527f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b03169063f3076c3a90606401600060405180830381600087803b1580156108e057600080fd5b505af11580156108f4573d6000803e3d6000fd5b505060408051888152600060208201819052918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e7925060600190505b60405180910390a15050505050565b63ffffffff81166001146109c15760405162461bcd60e51b815260206004820152603a60248201527f557064617465733a3a7375626d69744e65774f776e657273686970526f6f743a60448201527f20696e636f7272656374207478466f726d617456657273696f6e000000000000606482015260840161056a565b827f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190613bdc565b14610aae5760405162461bcd60e51b815260206004820152603460248201527f6572726f723a207375626d69744e65774f776e657273686970526f6f7420666f6044820152737220616e20696e636f727265637420766572736560601b606482015260840161056a565b610ab6612fe6565b610b435760405162461bcd60e51b815260206004820152605260248201527f6e6f7420726561647920666f72206f776e657273686970207375626d6973736960448201527f6f6e3a207665727365206e6f7420736574746c6564206f72206e657720545873606482015271081b9bdd081cdd589b5a5d1d1959081e595d60721b608482015260a40161056a565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03166371435c7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ba1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc59190613bdc565b610cbf577f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b031663a12cdbad6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4b9190613bdc565b8214610cbf5760405162461bcd60e51b815260206004820152603d60248201527f696e20612076657273652077697468206e6f205458732c206f776e657273686960448201527f7020726f6f742073686f756c642072656d61696e207468652073616d65000000606482015260840161056a565b60405163ca6f95db60e01b8152600481018390526000907f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b03169063ca6f95db906024016020604051808303816000875af1158015610d29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4d9190613bdc565b604051632bf660ef60e21b8152600060048201523360248201529091507f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b03169063afd983bc90604401600060405180830381600087803b158015610db857600080fd5b505af1158015610dcc573d6000803e3d6000fd5b50506040518392508591507faf90c4aa6579d46f1d1728fd0113c96d153d42aaa5ab1f5bc241a05c4fc622af90600090a350505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01604051602081830303815290604052805190602001209050919050565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed89190613b42565b6001600160a01b0316336001600160a01b031614610f085760405162461bcd60e51b815260040161056a90613b6b565b604051635e1d948760e11b8152600481018890527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03169063bc3b290e90602401602060405180830381865afa158015610f6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f919190613bc1565b15610fae5760405162461bcd60e51b815260040161056a90613bf5565b60405163249f9e7360e11b8152600481018890527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03169063493f3ce690602401602060405180830381865afa158015611013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110379190613bdc565b85146110855760405162461bcd60e51b815260206004820152601c60248201527f707265765472616e73526f6f7420646f6573206e6f74206d6174636800000000604482015260640161056a565b60405163213f03fb60e21b8152600481018890527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316906384fc0fec90602401602060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110e9190613bc1565b61122a57600061113387876040516020016105bb929190918252602082015260400190565b90506111758186868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124c692505050565b604051635a53a85b60e11b8152600481018a90526001600160a01b03918216917f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a66169063b4a750b690602401602060405180830381865afa1580156111de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112029190613b42565b6001600160a01b0316146112285760405162461bcd60e51b815260040161056a90613c40565b505b604051632383313160e01b815260048101889052602481018790524260448201526000907f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b0316906323833131906064016020604051808303816000875af11580156112a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c59190613bdc565b90508089146113165760405162461bcd60e51b815260206004820152601f60248201527f6572726f723a20696e636f727265637420756e69766572736520766572736500604482015260640161056a565b8087897f3622597e9085739b48cf129e1f6dfb4cb8c29aa6bccc1d92bc07791eb2fd1988868660405161134a929190613cb3565b60405180910390a4505050505050505050565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b031663aba3e1116040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113df9190613b42565b6001600160a01b0316336001600160a01b03161461143f5760405162461bcd60e51b815260206004820181905260248201527f4f6e6c792072656c6179206f662054587320697320617574686f72697a65642e604482015260640161056a565b827ff09c0c2e1067d84ab49d3bff959e45870f3417b16c65199accc451bca46e0d508383604051611471929190613cb3565b60405180910390a2505050565b600061149c8361148d84612f4f565b60408501516020860151611edb565b90505b92915050565b6000811580156114b3575082155b156114c05750600061149f565b5060009182526020526040902090565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b031663aba3e1116040518163ffffffff1660e01b8152600401602060405180830381865afa15801561152e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115529190613b42565b6001600160a01b0316336001600160a01b0316146115b25760405162461bcd60e51b815260206004820181905260248201527f4f6e6c792072656c6179206f662054587320697320617574686f72697a65642e604482015260640161056a565b63ffffffff83166001146116255760405162461bcd60e51b815260206004820152603460248201527f557064617465733a3a7375626d69744e6577545873526f6f743a20696e636f726044820152733932b1ba103a3c2337b936b0ba2b32b939b4b7b760611b606482015260840161056a565b857f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316635aca800e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a89190613bdc565b6116b3906001613cdd565b146117175760405162461bcd60e51b815260206004820152602e60248201527f6572726f723a207375626d69744e6577545873526f6f7420666f7220616e206960448201526d6e636f727265637420766572736560901b606482015260840161056a565b6000807f000000000000000000000000b383f452bb92a6b6d6e73f2edaa4d1f37685a5856001600160a01b031663ad71247e6040518163ffffffff1660e01b81526004016040805180830381865afa158015611777573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179b9190613cf5565b91509150816118125760405162461bcd60e51b815260206004820152603860248201527f6e6f7420726561647920746f20616363657074206e6577205458207375626d6960448201527f7373696f6e2c207665727365206e6f7420736574746c65640000000000000000606482015260840161056a565b8060ff166001148061182757508060ff166002145b61188b5760405162461bcd60e51b815260206004820152602f60248201527f7061737420766572736520656e64656420757020736574746c696e6720696e2060448201526e1a5b98dbdc9c9958dd081b195d995b608a1b606482015260840161056a565b856118f65786156118f65760405162461bcd60e51b815260206004820152602f60248201527f696e20612076657273652077697468206e6f205458732c20746865205458526f60448201526e1bdd081b5d5cdd081899481b9d5b1b608a1b606482015260840161056a565b60007f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b031663456c405a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197a9190613d2c565b905060006119908861047260ff85166002613e2d565b6040516323da0e0960e21b8152600481018b9052426024820152604481018a905260ff8086166064830152821660848201529091506000906001600160a01b037f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b91690638f6838249060a4016020604051808303816000875af1158015611a1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a3f9190613bdc565b90506001811115611abe577f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b0316634bb278f36040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611aa557600080fd5b505af1158015611ab9573d6000803e3d6000fd5b505050505b808a7f6f3984a8056b744a2405c513c3027efbcc8f00fb16be25a2e3fb772238b3455d8b868b8b604051611af59493929190613e39565b60405180910390a35050505050505050505050565b60405162461bcd60e51b815260206004820152603d60248201527f557064617465733a3a7375626d69744e65774f776e657273686970526f6f743a60448201527f206d6574686f64206e6f7420737570706f7274656420616e796d6f7265000000606482015260840161056a565b600081611ba15782600081518110611b9257611b92613e66565b6020026020010151905061149f565b6000611bae836002613e2d565b90508351811015611c275760405162461bcd60e51b815260206004820152603860248201527f6d65726b6c65526f6f743a206e6f7420656e6f756768206c6576656c7320676960448201527f76656e20746865206e756d626572206f66206c65617665730000000000000000606482015260840161056a565b611c32600282613e92565b90506000816001600160401b03811115611c4e57611c4e6134db565b604051908082528060200260200182016040528015611c77578160200160208202803683370190505b509050600060028651611c8a9190613e92565b905060005b81811015611d2357611cf487611ca6836002613ea6565b81518110611cb657611cb6613e66565b602002602001015188836002611ccc9190613ea6565b611cd7906001613cdd565b81518110611ce757611ce7613e66565b60200260200101516114a5565b838281518110611d0657611d06613e66565b602090810291909101015280611d1b81613ec5565b915050611c8f565b5060028651611d329190613ee0565b15611d9557611d6a8660018851611d499190613ef4565b81518110611d5957611d59613e66565b60200260200101516000801b6114a5565b828281518110611d7c57611d7c613e66565b6020908102919091010152611d92600182613cdd565b90505b60015b858160ff161015611eb457611dae600285613e92565b9350611dbb600283613ee0565b15611ddb57611dcb600283613e92565b611dd6906001613cdd565b611de6565b611de6600283613e92565b915083821115611df4578391505b60005b82811015611e6357611e3484611e0e836002613ea6565b81518110611e1e57611e1e613e66565b602002602001015185836002611ccc9190613ea6565b848281518110611e4657611e46613e66565b602090810291909101015280611e5b81613ec5565b915050611df7565b50815b84811015611ea1576000801b848281518110611e8457611e84613e66565b602090810291909101015280611e9981613ec5565b915050611e66565b5080611eac81613f0b565b915050611d98565b5081600081518110611ec857611ec8613e66565b6020026020010151935050505092915050565b6000805b84518163ffffffff161015611f6b57611ef9600284613ee0565b611f2057611f1984868363ffffffff1681518110611ce757611ce7613e66565b9350611f4c565b611f49858263ffffffff1681518110611f3b57611f3b613e66565b6020026020010151856114a5565b93505b611f57600284613e92565b925080611f6381613f2b565b915050611edf565b5081158015611f7957508285145b95945050505050565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fe0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120049190613b42565b6001600160a01b0316336001600160a01b0316146120345760405162461bcd60e51b815260040161056a90613b6b565b604051635e1d948760e11b8152600481018890527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03169063bc3b290e90602401602060405180830381865afa158015612099573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120bd9190613bc1565b156120da5760405162461bcd60e51b815260040161056a90613bf5565b60405163249f9e7360e11b8152600481018890527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03169063493f3ce690602401602060405180830381865afa15801561213f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121639190613bdc565b85146121b15760405162461bcd60e51b815260206004820152601c60248201527f707265765472616e73526f6f7420646f6573206e6f74206d6174636800000000604482015260640161056a565b60405163213f03fb60e21b8152600481018890527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316906384fc0fec90602401602060405180830381865afa158015612216573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223a9190613bc1565b61235657600061225f87876040516020016105bb929190918252602082015260400190565b90506122a18186868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124c692505050565b604051635a53a85b60e11b8152600481018a90526001600160a01b03918216917f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a66169063b4a750b690602401602060405180830381865afa15801561230a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232e9190613b42565b6001600160a01b0316146123545760405162461bcd60e51b815260040161056a90613c40565b505b604051632383313160e01b815260048101889052602481018790524260448201526000907f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b0316906323833131906064016020604051808303816000875af11580156123cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f19190613bdc565b90508087897f3622597e9085739b48cf129e1f6dfb4cb8c29aa6bccc1d92bc07791eb2fd19888686604051612427929190613cb3565b60405180910390a45050505050505050565b60607f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316636b87d24c6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612499573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124c19190810190613f4f565b905090565b60008060008084516041146124e1576000935050505061149f565b50505060208201516040830151604184015160ff16601b81101561250d5761250a601b82613fbc565b90505b8060ff16601b1415801561252557508060ff16601c14155b15612536576000935050505061149f565b60408051600081526020810180835288905260ff831691810191909152606081018490526080810183905260019060a0016020604051602081039080840390855afa158015612589573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b60608161268a5782516001146126115760405162461bcd60e51b815260206004820152603260248201527f6275696c6450726f6f663a206c6561766573206c656e677468206d75737420626044820152710652030206966206e4c6576656c73203d20360741b606482015260840161056a565b83156126855760405162461bcd60e51b815260206004820152603760248201527f6275696c6450726f6f663a206c656166506f73206d757374206265203020696660448201527f207468657265206973206f6e6c79206f6e65206c656166000000000000000000606482015260840161056a565b6128fa565b6000612697836002613e2d565b9050808451146126fa5760405162461bcd60e51b815260206004820152602860248201527f6e756d626572206f66206c6561766573206973206e6f74203d20706f7728322c6044820152676e4c6576656c732960c01b606482015260840161056a565b826001600160401b03811115612712576127126134db565b60405190808252806020026020018201604052801561273b578160200160208202803683370190505b509150612749600286613ee0565b15612777578361275a600187613ef4565b8151811061276a5761276a613e66565b602002602001015161279c565b83612783866001613cdd565b8151811061279357612793613e66565b60200260200101515b826000815181106127af576127af613e66565b60200260200101818152505060005b6127c9600185613ef4565b8160ff1610156128f7576127de600283613e92565b91506127eb600287613e92565b955060005b8281101561285c5761282d86612807836002613ea6565b8151811061281757612817613e66565b602002602001015187836002611ccc9190613ea6565b86828151811061283f5761283f613e66565b60209081029190910101528061285481613ec5565b9150506127f0565b50612868600287613ee0565b156128965784612879600188613ef4565b8151811061288957612889613e66565b60200260200101516128bb565b846128a2876001613cdd565b815181106128b2576128b2613e66565b60200260200101515b836128c7836001613fbc565b60ff16815181106128da576128da613e66565b6020908102919091010152806128ef81613f0b565b9150506127be565b50505b9392505050565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561295f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129839190613b42565b6001600160a01b0316336001600160a01b0316146129b35760405162461bcd60e51b815260040161056a90613b6b565b60408051606060208201819052600e60808301526d436f6e6669726d436c6f7375726560901b60a08301529181018690529081018490526000906129f99060c0016105bb565b9050612a3b8184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124c692505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a66169063b4a750b690602401602060405180830381865afa158015612aa4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac89190613b42565b6001600160a01b031614612aee5760405162461bcd60e51b815260040161056a90613fe1565b428411612b0d5760405162461bcd60e51b815260040161056a9061402e565b604051635e1d948760e11b8152600481018690527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03169063bc3b290e90602401602060405180830381865afa158015612b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b969190613bc1565b15612bb35760405162461bcd60e51b815260040161056a90614075565b6040516395592de760e01b8152600481018690527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316906395592de790602401602060405180830381865afa158015612c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c3c9190613bc1565b612cc35760405162461bcd60e51b815260206004820152604c60248201527f72657175657374556e697665727365436c6f737572653a20756e69766572736560448201527f20636c6f73757265206d75737420626520726571756573746564206265666f7260648201526b6520636f6e6669726d696e6760a01b608482015260a40161056a565b604051637983b61d60e11b81526004810186905260016024820181905260448201527f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b03169063f3076c3a90606401600060405180830381600087803b158015612d3357600080fd5b505af1158015612d47573d6000803e3d6000fd5b505060408051888152600160208201819052918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e792506060019050610936565b606060008263ffffffff166001600160401b03811115612daf57612daf6134db565b604051908082528060200260200182016040528015612dd8578160200160208202803683370190505b50905060005b8363ffffffff168163ffffffff161015612e3e57612dfd602086613cdd565b9450600085870151905080838363ffffffff1681518110612e2057612e20613e66565b60209081029190910101525080612e3681613f2b565b915050612dde565b50949350505050565b60405162461bcd60e51b815260206004820152603760248201527f557064617465733a3a7375626d69744e6577545873526f6f743a206d6574686f60448201527f64206e6f7420737570706f7274656420616e796d6f7265000000000000000000606482015260840161056a565b6003815b80841115612ee05781612ecb81613f0b565b9250612ed990508382613ea6565b9050612eb9565b5092915050565b6040805160008082526020820180845287905260ff861692820192909252606081018490526080810183905260019060a0016020604051602081039080840390855afa158015612f3b573d6000803e3d6000fd5b5050604051601f1901519695505050505050565b60606000602060408451612f6391906140c4565b612f6d91906140e9565b9050612f7a81602061410c565b612f85906040614138565b63ffffffff16835114612fda5760405162461bcd60e51b815260206004820152601b60248201527f696e636f72726563742073657269616c697a6564206c656e6774680000000000604482015260640161056a565b6128fa83604083612d8d565b6000807f000000000000000000000000b383f452bb92a6b6d6e73f2edaa4d1f37685a5856001600160a01b0316633287fc906040518163ffffffff1660e01b8152600401606060405180830381865afa158015613047573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061306b9190614160565b5060ff16159392505050565b7f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b0316635c0563b36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f99190613b42565b6001600160a01b0316336001600160a01b0316146131295760405162461bcd60e51b815260040161056a90613b6b565b60408051606060208201819052600e60808301526d52657175657374436c6f7375726560901b60a083015291810186905290810184905260009061316f9060c0016105bb565b90506131b18184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506124c692505050565b604051635a53a85b60e11b8152600481018790526001600160a01b03918216917f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a66169063b4a750b690602401602060405180830381865afa15801561321a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323e9190613b42565b6001600160a01b0316146132645760405162461bcd60e51b815260040161056a90613fe1565b4284116132835760405162461bcd60e51b815260040161056a9061402e565b604051635e1d948760e11b8152600481018690527f0000000000000000000000000e6f49ccf7dd5093886e4d314c2aea7839262a666001600160a01b03169063bc3b290e90602401602060405180830381865afa1580156132e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330c9190613bc1565b156133295760405162461bcd60e51b815260040161056a90614075565b604051637983b61d60e11b81526004810186905260016024820152600060448201527f0000000000000000000000008cfc5aab04e0699457b4399c9338f3bf8fd1c4b96001600160a01b03169063f3076c3a90606401600060405180830381600087803b15801561339957600080fd5b505af11580156133ad573d6000803e3d6000fd5b505060408051888152600160208201526000918101919091527f0ed3b4308efa69b7f291c4edd8287fe44fa4b4ad7e501e3dc05011e0e01298e792506060019050610936565b60008083601f84011261340557600080fd5b5081356001600160401b0381111561341c57600080fd5b60208301915083602082850101111561343457600080fd5b9250929050565b6000806000806060858703121561345157600080fd5b843593506020850135925060408501356001600160401b0381111561347557600080fd5b613481878288016133f3565b95989497509550505050565b803563ffffffff811681146134a157600080fd5b919050565b6000806000606084860312156134bb57600080fd5b83359250602084013591506134d26040850161348d565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715613519576135196134db565b604052919050565b60006001600160401b0382111561353a5761353a6134db565b50601f01601f191660200190565b600082601f83011261355957600080fd5b813561356c61356782613521565b6134f1565b81815284602083860101111561358157600080fd5b816020850160208301376000918101602001919091529392505050565b6000602082840312156135b057600080fd5b81356001600160401b038111156135c657600080fd5b6135d284828501613548565b949350505050565b6000602082840312156135ec57600080fd5b5035919050565b60008060008060008060008060c0898b03121561360f57600080fd5b8835975060208901359650604089013595506060890135945060808901356001600160401b038082111561364257600080fd5b61364e8c838d016133f3565b909650945060a08b013591508082111561366757600080fd5b506136748b828c016133f3565b999c989b5096995094979396929594505050565b60008060006040848603121561369d57600080fd5b8335925060208401356001600160401b038111156136ba57600080fd5b6136c6868287016133f3565b9497909650939450505050565b600080604083850312156136e657600080fd5b8235915060208301356001600160401b0381111561370357600080fd5b61370f85828601613548565b9150509250929050565b6000806040838503121561372c57600080fd5b50508035926020909101359150565b60008060008060008060a0878903121561375457600080fd5b8635955060208701359450604087013593506137726060880161348d565b925060808701356001600160401b0381111561378d57600080fd5b61379989828a016133f3565b979a9699509497509295939492505050565b600082601f8301126137bc57600080fd5b813560206001600160401b038211156137d7576137d76134db565b8160051b6137e68282016134f1565b928352848101820192828101908785111561380057600080fd5b83870192505b8483101561381f57823582529183019190830190613806565b979650505050505050565b6000806040838503121561383d57600080fd5b82356001600160401b0381111561385357600080fd5b61385f858286016137ab565b95602094909401359450505050565b6000806000806080858703121561388457600080fd5b8435935060208501356001600160401b038111156138a157600080fd5b6138ad878288016137ab565b949794965050505060408301359260600135919050565b600080600080600080600060a0888a0312156138df57600080fd5b87359650602088013595506040880135945060608801356001600160401b038082111561390b57600080fd5b6139178b838c016133f3565b909650945060808a013591508082111561393057600080fd5b5061393d8a828b016133f3565b989b979a50959850939692959293505050565b60005b8381101561396b578181015183820152602001613953565b8381111561397a576000848401525b50505050565b602081526000825180602084015261399f816040850160208701613950565b601f01601f19169190910160400192915050565b6000806000606084860312156139c857600080fd5b8335925060208401356001600160401b038111156139e557600080fd5b6139f1868287016137ab565b925050604084013590509250925092565b6020808252825182820181905260009190848201906040850190845b81811015613a3a57835183529284019291840191600101613a1e565b50909695505050505050565b600080600060608486031215613a5b57600080fd5b83356001600160401b03811115613a7157600080fd5b613a7d86828701613548565b935050602084013591506134d26040850161348d565b600080600080600060808688031215613aab57600080fd5b85359450602086013593506040860135925060608601356001600160401b03811115613ad657600080fd5b613ae2888289016133f3565b969995985093965092949392505050565b60ff81168114613b0257600080fd5b50565b60008060008060808587031215613b1b57600080fd5b843593506020850135613b2d81613af3565b93969395505050506040820135916060013590565b600060208284031215613b5457600080fd5b81516001600160a01b03811681146128fa57600080fd5b60208082526026908201527f4f6e6c792072656c6179206f6620756e6976657273657320697320617574686f6040820152653934bd32b21760d11b606082015260800190565b805180151581146134a157600080fd5b600060208284031215613bd357600080fd5b61149c82613bb1565b600060208284031215613bee57600080fd5b5051919050565b6020808252602b908201527f7365744e6577556e697665727365526f6f743a20756e69766572736520616c7260408201526a1958591e4818db1bdcd95960aa1b606082015260800190565b6020808252602a908201527f756e69766572736520726f6f7420757064617465207369676e6174757265206e6040820152691bdd0818dbdc9c9958dd60b21b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815260006135d2602083018486613c8a565b634e487b7160e01b600052601160045260246000fd5b60008219821115613cf057613cf0613cc7565b500190565b60008060408385031215613d0857600080fd5b613d1183613bb1565b91506020830151613d2181613af3565b809150509250929050565b600060208284031215613d3e57600080fd5b81516128fa81613af3565b600181815b80851115613d84578160001904821115613d6a57613d6a613cc7565b80851615613d7757918102915b93841c9390800290613d4e565b509250929050565b600082613d9b5750600161149f565b81613da85750600061149f565b8160018114613dbe5760028114613dc857613de4565b600191505061149f565b60ff841115613dd957613dd9613cc7565b50506001821b61149f565b5060208310610133831016604e8410600b8410161715613e07575081810a61149f565b613e118383613d49565b8060001904821115613e2557613e25613cc7565b029392505050565b600061149c8383613d8c565b84815260ff84166020820152606060408201526000613e5c606083018486613c8a565b9695505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601260045260246000fd5b600082613ea157613ea1613e7c565b500490565b6000816000190483118215151615613ec057613ec0613cc7565b500290565b6000600019821415613ed957613ed9613cc7565b5060010190565b600082613eef57613eef613e7c565b500690565b600082821015613f0657613f06613cc7565b500390565b600060ff821660ff811415613f2257613f22613cc7565b60010192915050565b600063ffffffff80831681811415613f4557613f45613cc7565b6001019392505050565b600060208284031215613f6157600080fd5b81516001600160401b03811115613f7757600080fd5b8201601f81018413613f8857600080fd5b8051613f9661356782613521565b818152856020838501011115613fab57600080fd5b611f79826020830160208601613950565b600060ff821660ff84168060ff03821115613fd957613fd9613cc7565b019392505050565b6020808252602d908201527f72657175657374556e697665727365436c6f737572653a207369676e6174757260408201526c19481b9bdd0818dbdc9c9958dd609a1b606082015260800190565b60208082526027908201527f72657175657374556e697665727365436c6f737572653a207265717565737420604082015266195e1c1a5c995960ca1b606082015260800190565b6020808252602f908201527f72657175657374556e697665727365436c6f737572653a20756e69766572736560408201526e08185b1c9958591e4818db1bdcd959608a1b606082015260800190565b600063ffffffff838116908316818110156140e1576140e1613cc7565b039392505050565b600063ffffffff8084168061410057614100613e7c565b92169190910492915050565b600063ffffffff8083168185168183048111821515161561412f5761412f613cc7565b02949350505050565b600063ffffffff80831681851680830382111561415757614157613cc7565b01949350505050565b60008060006060848603121561417557600080fd5b61417e84613bb1565b9250602084015161418e81613af3565b604085015190925061419f81613af3565b80915050925092509256fea26469706673582212203dc34040b3fffb8025efc8685ba698c1ff873bdd50dc2d2c62ae872f95c6413464736f6c634300080b0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Txn 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.