Sepolia Testnet

Contract

0x04eE7A915241A357e01c3320b764a96c6b84A7Ae

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
53896732024-02-29 20:10:24322 days ago1709237424  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PreimageOracle

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 999999 runs

Other Settings:
london EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 6 : PreimageOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import { IPreimageOracle } from "./interfaces/IPreimageOracle.sol";
import { PreimageKeyLib } from "./PreimageKeyLib.sol";
import { LibKeccak } from "@lib-keccak/LibKeccak.sol";
import "src/cannon/libraries/CannonErrors.sol";
import "src/cannon/libraries/CannonTypes.sol";

/// @title PreimageOracle
/// @notice A contract for storing permissioned pre-images.
/// @custom:attribution Solady <https://github.com/Vectorized/solady/blob/main/src/utils/MerkleProofLib.sol#L13-L43>
/// @custom:attribution Beacon Deposit Contract <0x00000000219ab540356cbb839cbe05303d7705fa>
contract PreimageOracle is IPreimageOracle {
    ////////////////////////////////////////////////////////////////
    //                   Constants & Immutables                   //
    ////////////////////////////////////////////////////////////////

    /// @notice The duration of the large preimage proposal challenge period.
    uint256 internal immutable CHALLENGE_PERIOD;
    /// @notice The minimum size of a preimage that can be proposed in the large preimage path.
    uint256 internal immutable MIN_LPP_SIZE_BYTES;
    /// @notice The depth of the keccak256 merkle tree. Supports up to 65,536 keccak blocks, or ~8.91MB preimages.
    uint256 public constant KECCAK_TREE_DEPTH = 16;
    /// @notice The maximum number of keccak blocks that can fit into the merkle tree.
    uint256 public constant MAX_LEAF_COUNT = 2 ** KECCAK_TREE_DEPTH - 1;

    ////////////////////////////////////////////////////////////////
    //                 Authorized Preimage Parts                  //
    ////////////////////////////////////////////////////////////////

    /// @notice Mapping of pre-image keys to pre-image lengths.
    mapping(bytes32 => uint256) public preimageLengths;
    /// @notice Mapping of pre-image keys to pre-image offsets to pre-image parts.
    mapping(bytes32 => mapping(uint256 => bytes32)) public preimageParts;
    /// @notice Mapping of pre-image keys to pre-image part offsets to preimage preparedness.
    mapping(bytes32 => mapping(uint256 => bool)) public preimagePartOk;

    ////////////////////////////////////////////////////////////////
    //                  Large Preimage Proposals                  //
    ////////////////////////////////////////////////////////////////

    /// @notice A raw leaf of the large preimage proposal merkle tree.
    struct Leaf {
        /// @notice The input absorbed for the block, exactly 136 bytes.
        bytes input;
        /// @notice The index of the block in the absorption process.
        uint256 index;
        /// @notice The hash of the internal state after absorbing the input.
        bytes32 stateCommitment;
    }

    /// @notice Unpacked keys for large preimage proposals.
    struct LargePreimageProposalKeys {
        /// @notice The claimant of the large preimage proposal.
        address claimant;
        /// @notice The UUID of the large preimage proposal.
        uint256 uuid;
    }

    /// @notice Static padding hashes. These values are persisted in storage, but are entirely immutable
    ///         after the constructor's execution.
    bytes32[KECCAK_TREE_DEPTH] public zeroHashes;
    /// @notice Append-only array of large preimage proposals for off-chain reference.
    LargePreimageProposalKeys[] public proposals;
    /// @notice Mapping of claimants to proposal UUIDs to the current branch path of the merkleization process.
    mapping(address => mapping(uint256 => bytes32[KECCAK_TREE_DEPTH])) public proposalBranches;
    /// @notice Mapping of claimants to proposal UUIDs to the timestamp of creation of the proposal as well as the
    /// challenged status.
    mapping(address => mapping(uint256 => LPPMetaData)) public proposalMetadata;
    /// @notice Mapping of claimants to proposal UUIDs to the preimage part picked up during the absorbtion process.
    mapping(address => mapping(uint256 => bytes32)) public proposalParts;
    /// @notice Mapping of claimants to proposal UUIDs to blocks which leaves were added to the merkle tree.
    mapping(address => mapping(uint256 => uint64[])) public proposalBlocks;

    ////////////////////////////////////////////////////////////////
    //                        Constructor                         //
    ////////////////////////////////////////////////////////////////

    constructor(uint256 _minProposalSize, uint256 _challengePeriod) {
        MIN_LPP_SIZE_BYTES = _minProposalSize;
        CHALLENGE_PERIOD = _challengePeriod;

        // Compute hashes in empty sparse Merkle tree. The first hash is not set, and kept as zero as the identity.
        for (uint256 height = 0; height < KECCAK_TREE_DEPTH - 1; height++) {
            zeroHashes[height + 1] = keccak256(abi.encodePacked(zeroHashes[height], zeroHashes[height]));
        }
    }

    ////////////////////////////////////////////////////////////////
    //             Standard Preimage Route (External)             //
    ////////////////////////////////////////////////////////////////

    /// @inheritdoc IPreimageOracle
    function readPreimage(bytes32 _key, uint256 _offset) external view returns (bytes32 dat_, uint256 datLen_) {
        require(preimagePartOk[_key][_offset], "pre-image must exist");

        // Calculate the length of the pre-image data
        // Add 8 for the length-prefix part
        datLen_ = 32;
        uint256 length = preimageLengths[_key];
        if (_offset + 32 >= length + 8) {
            datLen_ = length + 8 - _offset;
        }

        // Retrieve the pre-image data
        dat_ = preimageParts[_key][_offset];
    }

    /// @inheritdoc IPreimageOracle
    function loadLocalData(
        uint256 _ident,
        bytes32 _localContext,
        bytes32 _word,
        uint256 _size,
        uint256 _partOffset
    )
        external
        returns (bytes32 key_)
    {
        // Compute the localized key from the given local identifier.
        key_ = PreimageKeyLib.localizeIdent(_ident, _localContext);

        // Revert if the given part offset is not within bounds.
        if (_partOffset > _size + 8 || _size > 32) {
            revert PartOffsetOOB();
        }

        // Prepare the local data part at the given offset
        bytes32 part;
        assembly {
            // Clean the memory in [0x20, 0x40)
            mstore(0x20, 0x00)

            // Store the full local data in scratch space.
            mstore(0x00, shl(192, _size))
            mstore(0x08, _word)

            // Prepare the local data part at the requested offset.
            part := mload(_partOffset)
        }

        // Store the first part with `_partOffset`.
        preimagePartOk[key_][_partOffset] = true;
        preimageParts[key_][_partOffset] = part;
        // Assign the length of the preimage at the localized key.
        preimageLengths[key_] = _size;
    }

    /// @inheritdoc IPreimageOracle
    function loadKeccak256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external {
        uint256 size;
        bytes32 key;
        bytes32 part;
        assembly {
            // len(sig) + len(partOffset) + len(preimage offset) = 4 + 32 + 32 = 0x44
            size := calldataload(0x44)

            // revert if part offset >= size+8 (i.e. parts must be within bounds)
            if iszero(lt(_partOffset, add(size, 8))) {
                // Store "PartOffsetOOB()"
                mstore(0, 0xfe254987)
                // Revert with "PartOffsetOOB()"
                revert(0x1c, 4)
            }
            // we leave solidity slots 0x40 and 0x60 untouched,
            // and everything after as scratch-memory.
            let ptr := 0x80
            // put size as big-endian uint64 at start of pre-image
            mstore(ptr, shl(192, size))
            ptr := add(ptr, 8)
            // copy preimage payload into memory so we can hash and read it.
            calldatacopy(ptr, _preimage.offset, size)
            // Note that it includes the 8-byte big-endian uint64 length prefix.
            // this will be zero-padded at the end, since memory at end is clean.
            part := mload(add(sub(ptr, 8), _partOffset))
            let h := keccak256(ptr, size) // compute preimage keccak256 hash
            // mask out prefix byte, replace with type 2 byte
            key := or(and(h, not(shl(248, 0xFF))), shl(248, 2))
        }
        preimagePartOk[key][_partOffset] = true;
        preimageParts[key][_partOffset] = part;
        preimageLengths[key] = size;
    }

    /// @inheritdoc IPreimageOracle
    function loadSha256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external {
        uint256 size;
        bytes32 key;
        bytes32 part;
        assembly {
            // len(sig) + len(partOffset) + len(preimage offset) = 4 + 32 + 32 = 0x44
            size := calldataload(0x44)

            // revert if part offset >= size+8 (i.e. parts must be within bounds)
            if iszero(lt(_partOffset, add(size, 8))) {
                // Store "PartOffsetOOB()"
                mstore(0, 0xfe254987)
                // Revert with "PartOffsetOOB()"
                revert(0x1c, 4)
            }
            // we leave solidity slots 0x40 and 0x60 untouched,
            // and everything after as scratch-memory.
            let ptr := 0x80
            // put size as big-endian uint64 at start of pre-image
            mstore(ptr, shl(192, size))
            ptr := add(ptr, 8)
            // copy preimage payload into memory so we can hash and read it.
            calldatacopy(ptr, _preimage.offset, size)
            // Note that it includes the 8-byte big-endian uint64 length prefix.
            // this will be zero-padded at the end, since memory at end is clean.
            part := mload(add(sub(ptr, 8), _partOffset))

            // compute SHA2-256 hash with pre-compile
            let success :=
                staticcall(
                    gas(), // Forward all available gas
                    0x02, // Address of SHA-256 precompile
                    ptr, // Start of input data in memory
                    size, // Size of input data
                    0, // Store output in scratch memory
                    0x20 // Output is always 32 bytes
                )
            // Check if the staticcall succeeded
            if iszero(success) { revert(0, 0) }
            let h := mload(0) // get return data
            // mask out prefix byte, replace with type 4 byte
            key := or(and(h, not(shl(248, 0xFF))), shl(248, 4))
        }
        preimagePartOk[key][_partOffset] = true;
        preimageParts[key][_partOffset] = part;
        preimageLengths[key] = size;
    }

    // TODO 4844 point-evaluation preimage

    ////////////////////////////////////////////////////////////////
    //            Large Preimage Proposals (External)             //
    ////////////////////////////////////////////////////////////////

    /// @notice Returns the length of the `proposals` array
    function proposalCount() external view returns (uint256 count_) {
        count_ = proposals.length;
    }

    /// @notice Returns the length of the array with the block numbers of `addLeavesLPP` calls for a given large
    ///         preimage proposal.
    function proposalBlocksLen(address _claimant, uint256 _uuid) external view returns (uint256 len_) {
        len_ = proposalBlocks[_claimant][_uuid].length;
    }

    /// @notice Returns the length of the large preimage proposal challenge period.
    function challengePeriod() external view returns (uint256 challengePeriod_) {
        challengePeriod_ = CHALLENGE_PERIOD;
    }

    /// @notice Returns the minimum size (in bytes) of a large preimage proposal.
    function minProposalSize() external view returns (uint256 minProposalSize_) {
        minProposalSize_ = MIN_LPP_SIZE_BYTES;
    }

    /// @notice Initialize a large preimage proposal. Must be called before adding any leaves.
    function initLPP(uint256 _uuid, uint32 _partOffset, uint32 _claimedSize) external {
        // The caller of `addLeavesLPP` must be an EOA.
        if (msg.sender != tx.origin) revert NotEOA();

        // The part offset must be within the bounds of the claimed size + 8.
        if (_partOffset >= _claimedSize + 8) revert PartOffsetOOB();

        // The claimed size must be at least `MIN_LPP_SIZE_BYTES`.
        if (_claimedSize < MIN_LPP_SIZE_BYTES) revert InvalidInputSize();

        LPPMetaData metaData = proposalMetadata[msg.sender][_uuid];
        proposalMetadata[msg.sender][_uuid] = metaData.setPartOffset(_partOffset).setClaimedSize(_claimedSize);
        proposals.push(LargePreimageProposalKeys(msg.sender, _uuid));
    }

    /// @notice Adds a contiguous list of keccak state matrices to the merkle tree.
    function addLeavesLPP(
        uint256 _uuid,
        uint256 _inputStartBlock,
        bytes calldata _input,
        bytes32[] calldata _stateCommitments,
        bool _finalize
    )
        external
    {
        // If we're finalizing, pad the input for the submitter. If not, copy the input into memory verbatim.
        bytes memory input;
        if (_finalize) {
            input = LibKeccak.pad(_input);
        } else {
            input = _input;
        }

        // Pull storage variables onto the stack / into memory for operations.
        bytes32[KECCAK_TREE_DEPTH] memory branch = proposalBranches[msg.sender][_uuid];
        LPPMetaData metaData = proposalMetadata[msg.sender][_uuid];
        uint256 blocksProcessed = metaData.blocksProcessed();

        // The caller of `addLeavesLPP` must be an EOA.
        if (msg.sender != tx.origin) revert NotEOA();

        // Revert if the proposal has not been initialized. 0-size preimages are *not* allowed.
        if (metaData.claimedSize() == 0) revert NotInitialized();

        // Revert if the proposal has already been finalized. No leaves can be added after this point.
        if (metaData.timestamp() != 0) revert AlreadyFinalized();

        // Revert if the starting block is not the next block to be added. This is to aid submitters in ensuring that
        // they don't corrupt an in-progress proposal by submitting input out of order.
        if (blocksProcessed != _inputStartBlock) revert WrongStartingBlock();

        // Attempt to extract the preimage part from the input data, if the part offset is present in the current
        // chunk of input. This function has side effects, and will persist the preimage part to the caller's large
        // preimage proposal storage if the part offset is present in the input data.
        _extractPreimagePart(_input, _uuid, _finalize, metaData);

        assembly {
            let inputLen := mload(input)
            let inputPtr := add(input, 0x20)

            // The input length must be a multiple of 136 bytes
            // The input lenth / 136 must be equal to the number of state commitments.
            if or(mod(inputLen, 136), iszero(eq(_stateCommitments.length, div(inputLen, 136)))) {
                // Store "InvalidInputSize()" error selector
                mstore(0x00, 0x7b1daf1)
                revert(0x1C, 0x04)
            }

            // Allocate a hashing buffer the size of the leaf preimage.
            let hashBuf := mload(0x40)
            mstore(0x40, add(hashBuf, 0xC8))

            for { let i := 0 } lt(i, inputLen) { i := add(i, 136) } {
                // Copy the leaf preimage into the hashing buffer.
                let inputStartPtr := add(inputPtr, i)
                mstore(hashBuf, mload(inputStartPtr))
                mstore(add(hashBuf, 0x20), mload(add(inputStartPtr, 0x20)))
                mstore(add(hashBuf, 0x40), mload(add(inputStartPtr, 0x40)))
                mstore(add(hashBuf, 0x60), mload(add(inputStartPtr, 0x60)))
                mstore(add(hashBuf, 0x80), mload(add(inputStartPtr, 0x80)))
                mstore(add(hashBuf, 136), blocksProcessed)
                mstore(add(hashBuf, 168), calldataload(add(_stateCommitments.offset, shl(0x05, div(i, 136)))))

                // Hash the leaf preimage to get the node to add.
                let node := keccak256(hashBuf, 0xC8)

                // Increment the number of blocks processed.
                blocksProcessed := add(blocksProcessed, 0x01)

                // Add the node to the tree.
                let size := blocksProcessed
                for { let height := 0x00 } lt(height, shl(0x05, KECCAK_TREE_DEPTH)) { height := add(height, 0x20) } {
                    if and(size, 0x01) {
                        mstore(add(branch, height), node)
                        break
                    }

                    // Hash the node at `height` in the branch and the node together.
                    mstore(0x00, mload(add(branch, height)))
                    mstore(0x20, node)
                    node := keccak256(0x00, 0x40)
                    size := shr(0x01, size)
                }
            }
        }

        // Do not allow for posting preimages larger than the merkle tree can support.
        if (blocksProcessed > MAX_LEAF_COUNT) revert TreeSizeOverflow();

        // Update the proposal metadata to include the number of blocks processed and total bytes processed.
        metaData = metaData.setBlocksProcessed(uint32(blocksProcessed)).setBytesProcessed(
            uint32(_input.length + metaData.bytesProcessed())
        );
        // If the proposal is being finalized, set the timestamp to the current block timestamp. This begins the
        // challenge period, which must be waited out before the proposal can be finalized.
        if (_finalize) metaData = metaData.setTimestamp(uint64(block.timestamp));

        // Perist the latest branch to storage.
        proposalBranches[msg.sender][_uuid] = branch;
        // Persist the block number that these leaves were added in. This assists off-chain observers in reconstructing
        // the proposal merkle tree by querying block bodies.
        proposalBlocks[msg.sender][_uuid].push(uint64(block.number));
        // Persist the updated metadata to storage.
        proposalMetadata[msg.sender][_uuid] = metaData;
    }

    /// @notice Challenge a keccak256 block that was committed to in the merkle tree.
    function challengeLPP(
        address _claimant,
        uint256 _uuid,
        LibKeccak.StateMatrix memory _stateMatrix,
        Leaf calldata _preState,
        bytes32[] calldata _preStateProof,
        Leaf calldata _postState,
        bytes32[] calldata _postStateProof
    )
        external
    {
        // Verify that both leaves are present in the merkle tree.
        bytes32 root = getTreeRootLPP(_claimant, _uuid);
        if (
            !(
                _verify(_preStateProof, root, _preState.index, _hashLeaf(_preState))
                    && _verify(_postStateProof, root, _postState.index, _hashLeaf(_postState))
            )
        ) revert InvalidProof();

        // Verify that the prestate passed matches the intermediate state claimed in the leaf.
        if (keccak256(abi.encode(_stateMatrix)) != _preState.stateCommitment) revert InvalidPreimage();

        // Verify that the pre/post state are contiguous.
        if (_preState.index + 1 != _postState.index) revert StatesNotContiguous();

        // Absorb and permute the input bytes.
        LibKeccak.absorb(_stateMatrix, _postState.input);
        LibKeccak.permutation(_stateMatrix);

        // Verify that the post state hash doesn't match the expected hash.
        if (keccak256(abi.encode(_stateMatrix)) == _postState.stateCommitment) revert PostStateMatches();

        // Mark the keccak claim as countered.
        proposalMetadata[_claimant][_uuid] = proposalMetadata[_claimant][_uuid].setCountered(true);
    }

    /// @notice Challenge the first keccak256 block that was absorbed.
    function challengeFirstLPP(
        address _claimant,
        uint256 _uuid,
        Leaf calldata _postState,
        bytes32[] calldata _postStateProof
    )
        external
    {
        // Verify that the leaf is present in the merkle tree.
        bytes32 root = getTreeRootLPP(_claimant, _uuid);
        if (!_verify(_postStateProof, root, _postState.index, _hashLeaf(_postState))) revert InvalidProof();

        // The poststate index must be 0 in order to challenge it with this function.
        if (_postState.index != 0) revert StatesNotContiguous();

        // Absorb and permute the input bytes into a fresh state matrix.
        LibKeccak.StateMatrix memory stateMatrix;
        LibKeccak.absorb(stateMatrix, _postState.input);
        LibKeccak.permutation(stateMatrix);

        // Verify that the post state hash doesn't match the expected hash.
        if (keccak256(abi.encode(stateMatrix)) == _postState.stateCommitment) revert PostStateMatches();

        // Mark the keccak claim as countered.
        proposalMetadata[_claimant][_uuid] = proposalMetadata[_claimant][_uuid].setCountered(true);
    }

    /// @notice Finalize a large preimage proposal after the challenge period has passed.
    function squeezeLPP(
        address _claimant,
        uint256 _uuid,
        LibKeccak.StateMatrix memory _stateMatrix,
        Leaf calldata _preState,
        bytes32[] calldata _preStateProof,
        Leaf calldata _postState,
        bytes32[] calldata _postStateProof
    )
        external
    {
        LPPMetaData metaData = proposalMetadata[_claimant][_uuid];

        // Check if the proposal was countered.
        if (metaData.countered()) revert BadProposal();

        // Check if the challenge period has passed since the proposal was finalized.
        if (block.timestamp - metaData.timestamp() <= CHALLENGE_PERIOD) revert ActiveProposal();

        // Verify that both leaves are present in the merkle tree.
        bytes32 root = getTreeRootLPP(_claimant, _uuid);
        if (
            !(
                _verify(_preStateProof, root, _preState.index, _hashLeaf(_preState))
                    && _verify(_postStateProof, root, _postState.index, _hashLeaf(_postState))
            )
        ) revert InvalidProof();

        // Verify that the prestate passed matches the intermediate state claimed in the leaf.
        if (keccak256(abi.encode(_stateMatrix)) != _preState.stateCommitment) revert InvalidPreimage();

        // Verify that the pre/post state are contiguous.
        if (_preState.index + 1 != _postState.index || _postState.index != metaData.blocksProcessed() - 1) {
            revert StatesNotContiguous();
        }

        // The claimed size must match the actual size of the preimage.
        uint256 claimedSize = metaData.claimedSize();
        if (metaData.bytesProcessed() != claimedSize) revert InvalidInputSize();

        // Absorb and permute the input bytes. We perform no final verification on the state matrix here, since the
        // proposal has passed the challenge period and is considered valid.
        LibKeccak.absorb(_stateMatrix, _postState.input);
        LibKeccak.permutation(_stateMatrix);
        bytes32 finalDigest = LibKeccak.squeeze(_stateMatrix);

        // Write the preimage part to the authorized preimage parts mapping.
        uint256 partOffset = metaData.partOffset();
        preimagePartOk[finalDigest][partOffset] = true;
        preimageParts[finalDigest][partOffset] = proposalParts[_claimant][_uuid];
        preimageLengths[finalDigest] = claimedSize;
    }

    /// @notice Gets the current merkle root of the large preimage proposal tree.
    function getTreeRootLPP(address _owner, uint256 _uuid) public view returns (bytes32 treeRoot_) {
        uint256 size = proposalMetadata[_owner][_uuid].blocksProcessed();
        for (uint256 height = 0; height < KECCAK_TREE_DEPTH; height++) {
            if ((size & 1) == 1) {
                treeRoot_ = keccak256(abi.encode(proposalBranches[_owner][_uuid][height], treeRoot_));
            } else {
                treeRoot_ = keccak256(abi.encode(treeRoot_, zeroHashes[height]));
            }
            size >>= 1;
        }
    }

    /// @notice Attempts to persist the preimage part to the caller's large preimage proposal storage, if the preimage
    ///         part is present in the input data being posted.
    /// @param _input The portion of the preimage being posted.
    /// @param _uuid The UUID of the large preimage proposal.
    /// @param _finalize Whether or not the proposal is being finalized in the current call.
    /// @param _metaData The metadata of the large preimage proposal.
    function _extractPreimagePart(
        bytes calldata _input,
        uint256 _uuid,
        bool _finalize,
        LPPMetaData _metaData
    )
        internal
    {
        uint256 offset = _metaData.partOffset();
        uint256 claimedSize = _metaData.claimedSize();
        uint256 currentSize = _metaData.bytesProcessed();

        // Check if the part offset is present in the input data being posted. If it is, assign the part to the mapping.
        if (offset < 8 && currentSize == 0) {
            bytes32 preimagePart;
            assembly {
                mstore(0x00, shl(192, claimedSize))
                mstore(0x08, calldataload(_input.offset))
                preimagePart := mload(offset)
            }
            proposalParts[msg.sender][_uuid] = preimagePart;
        } else if (offset >= 8 && (offset = offset - 8) >= currentSize && offset < currentSize + _input.length) {
            uint256 relativeOffset = offset - currentSize;

            // Revert if the full preimage part is not available in the data we're absorbing. The submitter must
            // supply data that contains the full preimage part so that no partial preimage parts are stored in the
            // oracle. Partial parts are *only* allowed at the tail end of the preimage, where no more data is available
            // to be absorbed.
            if (relativeOffset + 32 >= _input.length && !_finalize) revert PartOffsetOOB();

            // If the preimage part is in the data we're about to absorb, persist the part to the caller's large
            // preimaage metadata.
            bytes32 preimagePart;
            assembly {
                preimagePart := calldataload(add(_input.offset, relativeOffset))
            }
            proposalParts[msg.sender][_uuid] = preimagePart;
        }
    }

    /// Check if leaf` at `index` verifies against the Merkle `root` and `branch`.
    /// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#is_valid_merkle_branch
    function _verify(
        bytes32[] calldata _proof,
        bytes32 _root,
        uint256 _index,
        bytes32 _leaf
    )
        internal
        pure
        returns (bool isValid_)
    {
        /// @solidity memory-safe-assembly
        assembly {
            function hashTwo(a, b) -> hash {
                mstore(0x00, a)
                mstore(0x20, b)
                hash := keccak256(0x00, 0x40)
            }

            let value := _leaf
            for { let i := 0x00 } lt(i, KECCAK_TREE_DEPTH) { i := add(i, 0x01) } {
                let branchValue := calldataload(add(_proof.offset, shl(0x05, i)))

                switch and(shr(i, _index), 0x01)
                case 1 { value := hashTwo(branchValue, value) }
                default { value := hashTwo(value, branchValue) }
            }

            isValid_ := eq(value, _root)
        }
    }

    /// @notice Hashes leaf data for the preimage proposals tree
    function _hashLeaf(Leaf memory _leaf) internal pure returns (bytes32 leaf_) {
        leaf_ = keccak256(abi.encodePacked(_leaf.input, _leaf.index, _leaf.stateCommitment));
    }
}

File 2 of 6 : IPreimageOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

/// @title IPreimageOracle
/// @notice Interface for a preimage oracle.
interface IPreimageOracle {
    /// @notice Reads a preimage from the oracle.
    /// @param _key The key of the preimage to read.
    /// @param _offset The offset of the preimage to read.
    /// @return dat_ The preimage data.
    /// @return datLen_ The length of the preimage data.
    function readPreimage(bytes32 _key, uint256 _offset) external view returns (bytes32 dat_, uint256 datLen_);

    /// @notice Loads of local data part into the preimage oracle.
    /// @param _ident The identifier of the local data.
    /// @param _localContext The local key context for the preimage oracle. Optionally, can be set as a constant
    ///                      if the caller only requires one set of local keys.
    /// @param _word The local data word.
    /// @param _size The number of bytes in `_word` to load.
    /// @param _partOffset The offset of the local data part to write to the oracle.
    /// @dev The local data parts are loaded into the preimage oracle under the context
    ///      of the caller - no other account can write to the caller's context
    ///      specific data.
    ///
    ///      There are 5 local data identifiers:
    ///      ┌────────────┬────────────────────────┐
    ///      │ Identifier │      Data              │
    ///      ├────────────┼────────────────────────┤
    ///      │          1 │ L1 Head Hash (bytes32) │
    ///      │          2 │ Output Root (bytes32)  │
    ///      │          3 │ Root Claim (bytes32)   │
    ///      │          4 │ L2 Block Number (u64)  │
    ///      │          5 │ Chain ID (u64)         │
    ///      └────────────┴────────────────────────┘
    function loadLocalData(
        uint256 _ident,
        bytes32 _localContext,
        bytes32 _word,
        uint256 _size,
        uint256 _partOffset
    )
        external
        returns (bytes32 key_);

    /// @notice Prepares a preimage to be read by keccak256 key, starting at the given offset and up to 32 bytes
    ///         (clipped at preimage length, if out of data).
    /// @param _partOffset The offset of the preimage to read.
    /// @param _preimage The preimage data.
    function loadKeccak256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external;

    /// @notice Prepares a preimage to be read by sha256 key, starting at the given offset and up to 32 bytes
    ///         (clipped at preimage length, if out of data).
    /// @param _partOffset The offset of the preimage to read.
    /// @param _preimage The preimage data.
    function loadSha256PreimagePart(uint256 _partOffset, bytes calldata _preimage) external;
}

File 3 of 6 : PreimageKeyLib.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

/// @title PreimageKeyLib
/// @notice Shared utilities for localizing local keys in the preimage oracle.
library PreimageKeyLib {
    /// @notice Generates a context-specific local key for the given local data identifier.
    /// @dev See `localize` for a description of the localization operation.
    /// @param _ident The identifier of the local data. [0, 32) bytes in size.
    /// @param _localContext The local context for the key.
    /// @return key_ The context-specific local key.
    function localizeIdent(uint256 _ident, bytes32 _localContext) internal view returns (bytes32 key_) {
        assembly {
            // Set the type byte in the given identifier to `1` (Local). We only care about
            // the [1, 32) bytes in this value.
            key_ := or(shl(248, 1), and(_ident, not(shl(248, 0xFF))))
        }
        // Localize the key with the given local context.
        key_ = localize(key_, _localContext);
    }

    /// @notice Localizes a given local data key for the caller's context.
    /// @dev The localization operation is defined as:
    ///      localize(k) = H(k .. sender .. local_context) & ~(0xFF << 248) | (0x01 << 248)
    ///      where H is the Keccak-256 hash function.
    /// @param _key The local data key to localize.
    /// @param _localContext The local context for the key.
    /// @return localizedKey_ The localized local data key.
    function localize(bytes32 _key, bytes32 _localContext) internal view returns (bytes32 localizedKey_) {
        assembly {
            // Grab the current free memory pointer to restore later.
            let ptr := mload(0x40)
            // Store the local data key and caller next to each other in memory for hashing.
            mstore(0, _key)
            mstore(0x20, caller())
            mstore(0x40, _localContext)
            // Localize the key with the above `localize` operation.
            localizedKey_ := or(and(keccak256(0, 0x60), not(shl(248, 0xFF))), shl(248, 1))
            // Restore the free memory pointer.
            mstore(0x40, ptr)
        }
    }

    /// @notice Computes and returns the key for a global keccak pre-image.
    /// @param _preimage The pre-image.
    /// @return key_ The pre-image key.
    function keccak256PreimageKey(bytes memory _preimage) internal pure returns (bytes32 key_) {
        assembly {
            // Grab the size of the `_preimage`
            let size := mload(_preimage)

            // Compute the pre-image keccak256 hash (aka the pre-image key)
            let h := keccak256(add(_preimage, 0x20), size)

            // Mask out prefix byte, replace with type 2 byte
            key_ := or(and(h, not(shl(248, 0xFF))), shl(248, 2))
        }
    }
}

File 4 of 6 : LibKeccak.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

/// @title LibKeccak
/// @notice An EVM implementation of the Keccak-f[1600] permutation.
/// @author clabby <https://github.com/clabby>
/// @custom:attribution geohot <https://github.com/geohot>
library LibKeccak {
    /// @notice The block size of the Keccak-f[1600] permutation, 1088 bits (136 bytes).
    uint256 internal constant BLOCK_SIZE_BYTES = 136;

    /// @notice The round constants for the keccak256 hash function. Packed in memory for efficient reading during the
    ///         permutation.
    bytes internal constant ROUND_CONSTANTS = abi.encode(
        0x00000000000000010000000000008082800000000000808a8000000080008000, // r1,r2,r3,r4
        0x000000000000808b000000008000000180000000800080818000000000008009, // r5,r6,r7,r8
        0x000000000000008a00000000000000880000000080008009000000008000000a, // r9,r10,r11,r12
        0x000000008000808b800000000000008b80000000000080898000000000008003, // r13,r14,r15,r16
        0x80000000000080028000000000000080000000000000800a800000008000000a, // r17,r18,r19,r20
        0x8000000080008081800000000000808000000000800000018000000080008008 // r21,r22,r23,r24
    );

    /// @notice A mask for 64-bit values.
    uint64 private constant U64_MASK = 0xFFFFFFFFFFFFFFFF;

    /// @notice The 5x5 state matrix for the keccak-f[1600] permutation.
    struct StateMatrix {
        uint64[25] state;
    }

    /// @notice Performs the Keccak-f[1600] permutation on the given 5x5 state matrix.
    function permutation(StateMatrix memory _stateMatrix) internal pure {
        // Pull the round constants into memory to avoid reallocation in the unrolled permutation loop.
        bytes memory roundConstants = ROUND_CONSTANTS;

        assembly {
            // Add 32 to the state matrix pointer to skip the data location field.
            let stateMatrixPtr := add(_stateMatrix, 0x20)
            let rcPtr := add(roundConstants, 0x20)

            // set a state element in the passed `StateMatrix` struct memory ptr.
            function setStateElem(ptr, idx, data) {
                mstore(add(ptr, shl(0x05, idx)), and(data, U64_MASK))
            }

            // fetch a state element from the passed `StateMatrix` struct memory ptr.
            function stateElem(ptr, idx) -> elem {
                elem := mload(add(ptr, shl(0x05, idx)))
            }

            // 64 bit logical shift
            function shl64(a, b) -> val {
                val := and(shl(a, b), U64_MASK)
            }

            // Performs an indivudual rho + pi computation, to be used in the full `thetaRhoPi` chain.
            function rhoPi(ptr, destIdx, srcIdx, fact, dt) {
                let xs1 := xor(stateElem(ptr, srcIdx), dt)
                let res := xor(shl(fact, xs1), shr(sub(64, fact), xs1))
                setStateElem(ptr, destIdx, res)
            }

            // xor a column in the state matrix
            function xorColumn(ptr, col) -> val {
                val :=
                    xor(
                        xor(xor(stateElem(ptr, col), stateElem(ptr, add(col, 5))), stateElem(ptr, add(col, 10))),
                        xor(stateElem(ptr, add(col, 15)), stateElem(ptr, add(col, 20)))
                    )
            }

            // Performs the `theta`, `rho`, and `pi` steps of the Keccak-f[1600] permutation on
            // the passed `StateMatrix` struct memory ptr.
            function thetaRhoPi(ptr) {
                // Theta
                let C0 := xorColumn(ptr, 0)
                let C1 := xorColumn(ptr, 1)
                let C2 := xorColumn(ptr, 2)
                let C3 := xorColumn(ptr, 3)
                let C4 := xorColumn(ptr, 4)
                let D0 := xor(xor(shl64(1, C1), shr(63, C1)), C4)
                let D1 := xor(xor(shl64(1, C2), shr(63, C2)), C0)
                let D2 := xor(xor(shl64(1, C3), shr(63, C3)), C1)
                let D3 := xor(xor(shl64(1, C4), shr(63, C4)), C2)
                let D4 := xor(xor(shl64(1, C0), shr(63, C0)), C3)

                let xs1 := xor(stateElem(ptr, 1), D1)
                let A1 := xor(shl(1, xs1), shr(63, xs1))

                setStateElem(ptr, 0, xor(stateElem(ptr, 0), D0))
                rhoPi(ptr, 1, 6, 44, D1)
                rhoPi(ptr, 6, 9, 20, D4)
                rhoPi(ptr, 9, 22, 61, D2)
                rhoPi(ptr, 22, 14, 39, D4)
                rhoPi(ptr, 14, 20, 18, D0)
                rhoPi(ptr, 20, 2, 62, D2)
                rhoPi(ptr, 2, 12, 43, D2)
                rhoPi(ptr, 12, 13, 25, D3)
                rhoPi(ptr, 13, 19, 8, D4)
                rhoPi(ptr, 19, 23, 56, D3)
                rhoPi(ptr, 23, 15, 41, D0)
                rhoPi(ptr, 15, 4, 27, D4)
                rhoPi(ptr, 4, 24, 14, D4)
                rhoPi(ptr, 24, 21, 2, D1)
                rhoPi(ptr, 21, 8, 55, D3)
                rhoPi(ptr, 8, 16, 45, D1)
                rhoPi(ptr, 16, 5, 36, D0)
                rhoPi(ptr, 5, 3, 28, D3)
                rhoPi(ptr, 3, 18, 21, D3)
                rhoPi(ptr, 18, 17, 15, D2)
                rhoPi(ptr, 17, 11, 10, D1)
                rhoPi(ptr, 11, 7, 6, D2)
                rhoPi(ptr, 7, 10, 3, D0)
                setStateElem(ptr, 10, A1)
            }

            // Inner `chi` function, unrolled in `chi` for performance.
            function innerChi(ptr, start) {
                let A0 := stateElem(ptr, start)
                let A1 := stateElem(ptr, add(start, 1))
                let A2 := stateElem(ptr, add(start, 2))
                let A3 := stateElem(ptr, add(start, 3))
                let A4 := stateElem(ptr, add(start, 4))

                setStateElem(ptr, start, xor(A0, and(not(A1), A2)))
                setStateElem(ptr, add(start, 1), xor(A1, and(not(A2), A3)))
                setStateElem(ptr, add(start, 2), xor(A2, and(not(A3), A4)))
                setStateElem(ptr, add(start, 3), xor(A3, and(not(A4), A0)))
                setStateElem(ptr, add(start, 4), xor(A4, and(not(A0), A1)))
            }

            // Performs the `chi` step of the Keccak-f[1600] permutation on the passed `StateMatrix` struct memory ptr
            function chi(ptr) {
                innerChi(ptr, 0)
                innerChi(ptr, 5)
                innerChi(ptr, 10)
                innerChi(ptr, 15)
                innerChi(ptr, 20)
            }

            // Perform the full Keccak-f[1600] permutation on a `StateMatrix` struct memory ptr for a given round.
            function permute(ptr, roundsPtr, round) {
                // Theta, Rho, Pi, Chi
                thetaRhoPi(ptr)
                chi(ptr)
                // Iota
                let roundConst := shr(192, mload(add(roundsPtr, shl(0x03, round))))
                setStateElem(ptr, 0, xor(stateElem(ptr, 0), roundConst))
            }

            // Unroll the permutation loop.
            permute(stateMatrixPtr, rcPtr, 0)
            permute(stateMatrixPtr, rcPtr, 1)
            permute(stateMatrixPtr, rcPtr, 2)
            permute(stateMatrixPtr, rcPtr, 3)
            permute(stateMatrixPtr, rcPtr, 4)
            permute(stateMatrixPtr, rcPtr, 5)
            permute(stateMatrixPtr, rcPtr, 6)
            permute(stateMatrixPtr, rcPtr, 7)
            permute(stateMatrixPtr, rcPtr, 8)
            permute(stateMatrixPtr, rcPtr, 9)
            permute(stateMatrixPtr, rcPtr, 10)
            permute(stateMatrixPtr, rcPtr, 11)
            permute(stateMatrixPtr, rcPtr, 12)
            permute(stateMatrixPtr, rcPtr, 13)
            permute(stateMatrixPtr, rcPtr, 14)
            permute(stateMatrixPtr, rcPtr, 15)
            permute(stateMatrixPtr, rcPtr, 16)
            permute(stateMatrixPtr, rcPtr, 17)
            permute(stateMatrixPtr, rcPtr, 18)
            permute(stateMatrixPtr, rcPtr, 19)
            permute(stateMatrixPtr, rcPtr, 20)
            permute(stateMatrixPtr, rcPtr, 21)
            permute(stateMatrixPtr, rcPtr, 22)
            permute(stateMatrixPtr, rcPtr, 23)
        }
    }

    /// @notice Absorb a fixed-sized block into the sponge.
    function absorb(StateMatrix memory _stateMatrix, bytes memory _input) internal pure {
        assembly {
            // The input must be 1088 bits long.
            if iszero(eq(mload(_input), 136)) { revert(0, 0) }

            let dataPtr := add(_input, 0x20)
            let statePtr := add(_stateMatrix, 0x20)

            // set a state element in the passed `StateMatrix` struct memory ptr.
            function setStateElem(ptr, idx, data) {
                mstore(add(ptr, shl(0x05, idx)), and(data, U64_MASK))
            }

            // fetch a state element from the passed `StateMatrix` struct memory ptr.
            function stateElem(ptr, idx) -> elem {
                elem := mload(add(ptr, shl(0x05, idx)))
            }

            // Inner sha3 absorb XOR function
            function absorbInner(stateMatrixPtr, inputPtr, idx) {
                let boWord := mload(add(inputPtr, shl(3, idx)))

                let res :=
                    or(
                        or(
                            or(shl(56, byte(7, boWord)), shl(48, byte(6, boWord))),
                            or(shl(40, byte(5, boWord)), shl(32, byte(4, boWord)))
                        ),
                        or(
                            or(shl(24, byte(3, boWord)), shl(16, byte(2, boWord))),
                            or(shl(8, byte(1, boWord)), byte(0, boWord))
                        )
                    )
                setStateElem(stateMatrixPtr, idx, xor(stateElem(stateMatrixPtr, idx), res))
            }

            // Unroll the input XOR loop.
            absorbInner(statePtr, dataPtr, 0)
            absorbInner(statePtr, dataPtr, 1)
            absorbInner(statePtr, dataPtr, 2)
            absorbInner(statePtr, dataPtr, 3)
            absorbInner(statePtr, dataPtr, 4)
            absorbInner(statePtr, dataPtr, 5)
            absorbInner(statePtr, dataPtr, 6)
            absorbInner(statePtr, dataPtr, 7)
            absorbInner(statePtr, dataPtr, 8)
            absorbInner(statePtr, dataPtr, 9)
            absorbInner(statePtr, dataPtr, 10)
            absorbInner(statePtr, dataPtr, 11)
            absorbInner(statePtr, dataPtr, 12)
            absorbInner(statePtr, dataPtr, 13)
            absorbInner(statePtr, dataPtr, 14)
            absorbInner(statePtr, dataPtr, 15)
            absorbInner(statePtr, dataPtr, 16)
        }
    }

    /// @notice Squeezes the final keccak256 digest from the passed `StateMatrix`.
    function squeeze(StateMatrix memory _stateMatrix) internal pure returns (bytes32 hash_) {
        assembly {
            // 64 bit logical shift
            function shl64(a, b) -> val {
                val := and(shl(a, b), U64_MASK)
            }

            // convert a big endian 64-bit value to a little endian 64-bit value.
            function toLE(beVal) -> leVal {
                beVal := or(and(shl64(8, beVal), 0xFF00FF00FF00FF00), and(shr(8, beVal), 0x00FF00FF00FF00FF))
                beVal := or(and(shl64(16, beVal), 0xFFFF0000FFFF0000), and(shr(16, beVal), 0x0000FFFF0000FFFF))
                leVal := or(shl64(32, beVal), shr(32, beVal))
            }

            // fetch a state element from the passed `StateMatrix` struct memory ptr.
            function stateElem(ptr, idx) -> elem {
                elem := mload(add(ptr, shl(0x05, idx)))
            }

            let stateMatrixPtr := add(_stateMatrix, 0x20)
            hash_ :=
                or(
                    or(shl(192, toLE(stateElem(stateMatrixPtr, 0))), shl(128, toLE(stateElem(stateMatrixPtr, 1)))),
                    or(shl(64, toLE(stateElem(stateMatrixPtr, 2))), toLE(stateElem(stateMatrixPtr, 3)))
                )
        }
    }

    /// @notice Pads input data to an even multiple of the Keccak-f[1600] permutation block size, 1088 bits (136 bytes).
    function pad(bytes calldata _data) internal pure returns (bytes memory padded_) {
        assembly {
            padded_ := mload(0x40)

            // Grab the original length of `_data`
            let len := _data.length

            let dataPtr := add(padded_, 0x20)
            let endPtr := add(dataPtr, len)

            // Copy the data into memory.
            calldatacopy(dataPtr, _data.offset, len)

            let modBlockSize := mod(len, BLOCK_SIZE_BYTES)
            switch modBlockSize
            case false {
                // If the input is a perfect multiple of the block size, then we add a full extra block of padding.
                mstore8(endPtr, 0x01)
                mstore8(sub(add(endPtr, BLOCK_SIZE_BYTES), 0x01), 0x80)

                // Update the length of the data to include the padding.
                mstore(padded_, add(len, BLOCK_SIZE_BYTES))
            }
            default {
                // If the input is not a perfect multiple of the block size, then we add a partial block of padding.
                // This should entail a set bit after the input, followed by as many zero bits as necessary to fill
                // the block, followed by a single 1 bit in the lowest-order bit of the final block.

                let remaining := sub(BLOCK_SIZE_BYTES, modBlockSize)
                let newLen := add(len, remaining)

                // Store the padding bits.
                mstore8(add(dataPtr, sub(newLen, 0x01)), 0x80)
                mstore8(endPtr, or(byte(0, mload(endPtr)), 0x01))

                // Update the length of the data to include the padding. The length should be a multiple of the
                // block size after this.
                mstore(padded_, newLen)
            }

            // Update the free memory pointer.
            mstore(0x40, add(padded_, and(add(mload(padded_), 0x3F), not(0x1F))))
        }
    }

    /// @notice Pads input data to an even multiple of the Keccak-f[1600] permutation block size, 1088 bits (136 bytes).
    /// @dev Can clobber memory after `_data` if `_data` is not already a multiple of 136 bytes.
    function padMemory(bytes memory _data) internal pure returns (bytes memory padded_) {
        assembly {
            padded_ := mload(0x40)

            // Grab the original length of `_data`
            let len := mload(_data)

            let dataPtr := add(padded_, 0x20)
            let endPtr := add(dataPtr, len)

            // Copy the data.
            let originalDataPtr := add(_data, 0x20)
            for { let i := 0 } lt(i, len) { i := add(i, 0x20) } {
                mstore(add(dataPtr, i), mload(add(originalDataPtr, i)))
            }

            let modBlockSize := mod(len, BLOCK_SIZE_BYTES)
            switch modBlockSize
            case false {
                // If the input is a perfect multiple of the block size, then we add a full extra block of padding.
                mstore8(endPtr, 0x01)
                mstore8(sub(add(endPtr, BLOCK_SIZE_BYTES), 0x01), 0x80)

                // Update the length of the data to include the padding.
                mstore(padded_, add(len, BLOCK_SIZE_BYTES))
            }
            default {
                // If the input is not a perfect multiple of the block size, then we add a partial block of padding.
                // This should entail a set bit after the input, followed by as many zero bits as necessary to fill
                // the block, followed by a single 1 bit in the lowest-order bit of the final block.

                let remaining := sub(BLOCK_SIZE_BYTES, modBlockSize)
                let newLen := add(len, remaining)

                // Store the padding bits.
                mstore8(add(dataPtr, sub(newLen, 0x01)), 0x80)
                mstore8(endPtr, or(byte(0, mload(endPtr)), 0x01))

                // Update the length of the data to include the padding. The length should be a multiple of the
                // block size after this.
                mstore(padded_, newLen)
            }

            // Update the free memory pointer.
            mstore(0x40, add(padded_, and(add(mload(padded_), 0x3F), not(0x1F))))
        }
    }
}

File 5 of 6 : CannonErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

/// @notice Thrown when a passed part offset is out of bounds.
error PartOffsetOOB();

/// @notice Thrown when a merkle proof fails to verify.
error InvalidProof();

/// @notice Thrown when the prestate preimage doesn't match the claimed preimage.
error InvalidPreimage();

/// @notice Thrown when a leaf with an invalid input size is added.
error InvalidInputSize();

/// @notice Thrown when data is submitted out of order in a large preimage proposal.
error WrongStartingBlock();

/// @notice Thrown when the pre and post states passed aren't contiguous.
error StatesNotContiguous();

/// @notice Thrown when the permutation yields the expected result.
error PostStateMatches();

/// @notice Thrown when the preimage is too large to fit in the tree.
error TreeSizeOverflow();

/// @notice Thrown when the preimage proposal has already been finalized.
error AlreadyFinalized();

/// @notice Thrown when the proposal has not matured past the challenge period.
error ActiveProposal();

/// @notice Thrown when attempting to finalize a proposal that has been challenged.
error BadProposal();

/// @notice Thrown when attempting to add leaves to a preimage proposal that has not been initialized.
error NotInitialized();

/// @notice Thrown when the caller of a function is not an EOA.
error NotEOA();

File 6 of 6 : CannonTypes.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

using LPPMetadataLib for LPPMetaData global;

/// @notice Packed LPP metadata.
/// ┌─────────────┬────────────────────────────────────────────┐
/// │ Bit Offsets │                Description                 │
/// ├─────────────┼────────────────────────────────────────────┤
/// │ [0, 64)     │ Timestamp (Finalized - All data available) │
/// │ [64, 96)    │ Part Offset                                │
/// │ [96, 128)   │ Claimed Size                               │
/// │ [128, 160)  │ Blocks Processed (Inclusive of Padding)    │
/// │ [160, 192)  │ Bytes Processed (Non-inclusive of Padding) │
/// │ [192, 256)  │ Countered                                  │
/// └─────────────┴────────────────────────────────────────────┘
type LPPMetaData is bytes32;

/// @notice LPP metadata UDT extension functions.
library LPPMetadataLib {
    uint256 private constant U64_MASK = 0xFFFFFFFFFFFFFFFF;
    uint256 private constant U32_MASK = 0xFFFFFFFF;

    function setTimestamp(LPPMetaData _self, uint64 _timestamp) internal pure returns (LPPMetaData self_) {
        assembly {
            self_ := or(shl(192, _timestamp), and(_self, not(shl(192, U64_MASK))))
        }
    }

    function setPartOffset(LPPMetaData _self, uint32 _partOffset) internal pure returns (LPPMetaData self_) {
        assembly {
            self_ := or(shl(160, _partOffset), and(_self, not(shl(160, U32_MASK))))
        }
    }

    function setClaimedSize(LPPMetaData _self, uint32 _claimedSize) internal pure returns (LPPMetaData self_) {
        assembly {
            self_ := or(shl(128, _claimedSize), and(_self, not(shl(128, U32_MASK))))
        }
    }

    function setBlocksProcessed(LPPMetaData _self, uint32 _blocksProcessed) internal pure returns (LPPMetaData self_) {
        assembly {
            self_ := or(shl(96, _blocksProcessed), and(_self, not(shl(96, U32_MASK))))
        }
    }

    function setBytesProcessed(LPPMetaData _self, uint32 _bytesProcessed) internal pure returns (LPPMetaData self_) {
        assembly {
            self_ := or(shl(64, _bytesProcessed), and(_self, not(shl(64, U32_MASK))))
        }
    }

    function setCountered(LPPMetaData _self, bool _countered) internal pure returns (LPPMetaData self_) {
        assembly {
            self_ := or(_countered, and(_self, not(U64_MASK)))
        }
    }

    function timestamp(LPPMetaData _self) internal pure returns (uint64 timestamp_) {
        assembly {
            timestamp_ := shr(192, _self)
        }
    }

    function partOffset(LPPMetaData _self) internal pure returns (uint64 partOffset_) {
        assembly {
            partOffset_ := and(shr(160, _self), U32_MASK)
        }
    }

    function claimedSize(LPPMetaData _self) internal pure returns (uint32 claimedSize_) {
        assembly {
            claimedSize_ := and(shr(128, _self), U32_MASK)
        }
    }

    function blocksProcessed(LPPMetaData _self) internal pure returns (uint32 blocksProcessed_) {
        assembly {
            blocksProcessed_ := and(shr(96, _self), U32_MASK)
        }
    }

    function bytesProcessed(LPPMetaData _self) internal pure returns (uint32 bytesProcessed_) {
        assembly {
            bytesProcessed_ := and(shr(64, _self), U32_MASK)
        }
    }

    function countered(LPPMetaData _self) internal pure returns (bool countered_) {
        assembly {
            countered_ := and(_self, U64_MASK)
        }
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@rari-capital/solmate/=lib/solmate/",
    "@cwia/=lib/clones-with-immutable-args/src/",
    "@lib-keccak/=lib/lib-keccak/contracts/lib/",
    "forge-std/=lib/forge-std/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "safe-contracts/=lib/safe-contracts/contracts/",
    "kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/",
    "solady/=lib/solady/src/",
    "@eth-optimism/=node_modules/@eth-optimism/",
    "clones-with-immutable-args/=lib/clones-with-immutable-args/src/",
    "lib-keccak/=lib/lib-keccak/contracts/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_minProposalSize","type":"uint256"},{"internalType":"uint256","name":"_challengePeriod","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActiveProposal","type":"error"},{"inputs":[],"name":"AlreadyFinalized","type":"error"},{"inputs":[],"name":"BadProposal","type":"error"},{"inputs":[],"name":"InvalidInputSize","type":"error"},{"inputs":[],"name":"InvalidPreimage","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"NotEOA","type":"error"},{"inputs":[],"name":"NotInitialized","type":"error"},{"inputs":[],"name":"PartOffsetOOB","type":"error"},{"inputs":[],"name":"PostStateMatches","type":"error"},{"inputs":[],"name":"StatesNotContiguous","type":"error"},{"inputs":[],"name":"TreeSizeOverflow","type":"error"},{"inputs":[],"name":"WrongStartingBlock","type":"error"},{"inputs":[],"name":"KECCAK_TREE_DEPTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LEAF_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_uuid","type":"uint256"},{"internalType":"uint256","name":"_inputStartBlock","type":"uint256"},{"internalType":"bytes","name":"_input","type":"bytes"},{"internalType":"bytes32[]","name":"_stateCommitments","type":"bytes32[]"},{"internalType":"bool","name":"_finalize","type":"bool"}],"name":"addLeavesLPP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"uint256","name":"_uuid","type":"uint256"},{"components":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32","name":"stateCommitment","type":"bytes32"}],"internalType":"struct PreimageOracle.Leaf","name":"_postState","type":"tuple"},{"internalType":"bytes32[]","name":"_postStateProof","type":"bytes32[]"}],"name":"challengeFirstLPP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"uint256","name":"_uuid","type":"uint256"},{"components":[{"internalType":"uint64[25]","name":"state","type":"uint64[25]"}],"internalType":"struct LibKeccak.StateMatrix","name":"_stateMatrix","type":"tuple"},{"components":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32","name":"stateCommitment","type":"bytes32"}],"internalType":"struct PreimageOracle.Leaf","name":"_preState","type":"tuple"},{"internalType":"bytes32[]","name":"_preStateProof","type":"bytes32[]"},{"components":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32","name":"stateCommitment","type":"bytes32"}],"internalType":"struct PreimageOracle.Leaf","name":"_postState","type":"tuple"},{"internalType":"bytes32[]","name":"_postStateProof","type":"bytes32[]"}],"name":"challengeLPP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"challengePeriod","outputs":[{"internalType":"uint256","name":"challengePeriod_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_uuid","type":"uint256"}],"name":"getTreeRootLPP","outputs":[{"internalType":"bytes32","name":"treeRoot_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_uuid","type":"uint256"},{"internalType":"uint32","name":"_partOffset","type":"uint32"},{"internalType":"uint32","name":"_claimedSize","type":"uint32"}],"name":"initLPP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_partOffset","type":"uint256"},{"internalType":"bytes","name":"_preimage","type":"bytes"}],"name":"loadKeccak256PreimagePart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ident","type":"uint256"},{"internalType":"bytes32","name":"_localContext","type":"bytes32"},{"internalType":"bytes32","name":"_word","type":"bytes32"},{"internalType":"uint256","name":"_size","type":"uint256"},{"internalType":"uint256","name":"_partOffset","type":"uint256"}],"name":"loadLocalData","outputs":[{"internalType":"bytes32","name":"key_","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_partOffset","type":"uint256"},{"internalType":"bytes","name":"_preimage","type":"bytes"}],"name":"loadSha256PreimagePart","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minProposalSize","outputs":[{"internalType":"uint256","name":"minProposalSize_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"preimageLengths","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"preimagePartOk","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"preimageParts","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalBlocks","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"uint256","name":"_uuid","type":"uint256"}],"name":"proposalBlocksLen","outputs":[{"internalType":"uint256","name":"len_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalBranches","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"count_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalMetadata","outputs":[{"internalType":"LPPMetaData","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalParts","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"address","name":"claimant","type":"address"},{"internalType":"uint256","name":"uuid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_key","type":"bytes32"},{"internalType":"uint256","name":"_offset","type":"uint256"}],"name":"readPreimage","outputs":[{"internalType":"bytes32","name":"dat_","type":"bytes32"},{"internalType":"uint256","name":"datLen_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_claimant","type":"address"},{"internalType":"uint256","name":"_uuid","type":"uint256"},{"components":[{"internalType":"uint64[25]","name":"state","type":"uint64[25]"}],"internalType":"struct LibKeccak.StateMatrix","name":"_stateMatrix","type":"tuple"},{"components":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32","name":"stateCommitment","type":"bytes32"}],"internalType":"struct PreimageOracle.Leaf","name":"_preState","type":"tuple"},{"internalType":"bytes32[]","name":"_preStateProof","type":"bytes32[]"},{"components":[{"internalType":"bytes","name":"input","type":"bytes"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"bytes32","name":"stateCommitment","type":"bytes32"}],"internalType":"struct PreimageOracle.Leaf","name":"_postState","type":"tuple"},{"internalType":"bytes32[]","name":"_postStateProof","type":"bytes32[]"}],"name":"squeezeLPP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"zeroHashes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b50604051620032ee380380620032ee8339810160408190526200003491620000f3565b60a0829052608081905260005b6200004f600160106200012e565b811015620000ea57600381601081106200006d576200006d62000148565b01546003826010811062000085576200008562000148565b0154604080516020810193909352820152606001604051602081830303815290604052805190602001206003826001620000c091906200015e565b60108110620000d357620000d362000148565b015580620000e18162000179565b91505062000041565b50505062000195565b600080604083850312156200010757600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b60008282101562000143576200014362000118565b500390565b634e487b7160e01b600052603260045260246000fd5b6000821982111562000174576200017462000118565b500190565b6000600182016200018e576200018e62000118565b5060010190565b60805160a051613125620001c9600039600081816103db015261175501526000818161044f015261100201526131256000f3fe608060405234801561001057600080fd5b50600436106101a35760003560e01c80638dc4be11116100ee578063dd24f9bf11610097578063ec5efcbc11610071578063ec5efcbc1461043a578063f3f480d91461044d578063faf37bc714610473578063fef2b4ed1461048657600080fd5b8063dd24f9bf146103d9578063e03110e1146103ff578063e15926111461042757600080fd5b8063b4801e61116100c8578063b4801e61146103ab578063d18534b5146103be578063da35c664146103d157600080fd5b80638dc4be111461032b5780639d53a6481461033e578063b2e67ba81461038057600080fd5b806361238bde116101505780637ac547671161012a5780637ac54767146102ae5780638542cf50146102c1578063882856ef146102ff57600080fd5b806361238bde146102455780636551927b146102705780637917de1d1461029b57600080fd5b80633909af5c116101815780633909af5c146102155780634d52b4c91461022a57806352f0f3ad1461023257600080fd5b8063013cf08b146101a85780630359a563146101ec5780632055b36b1461020d575b600080fd5b6101bb6101b6366004612768565b6104a6565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b6101ff6101fa3660046127aa565b6104eb565b6040519081526020016101e3565b6101ff601081565b6102286102233660046129a5565b610623565b005b6101ff610871565b6101ff610240366004612a91565b61088c565b6101ff610253366004612acc565b600160209081526000928352604080842090915290825290205481565b6101ff61027e3660046127aa565b601560209081526000928352604080842090915290825290205481565b6102286102a9366004612b30565b610961565b6101ff6102bc366004612768565b610def565b6102ef6102cf366004612acc565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016101e3565b61031261030d366004612bcc565b610e06565b60405167ffffffffffffffff90911681526020016101e3565b610228610339366004612bff565b610e60565b6101ff61034c3660046127aa565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601760209081526040808320938352929052205490565b6101ff61038e3660046127aa565b601660209081526000928352604080842090915290825290205481565b6101ff6103b9366004612bcc565b610f5b565b6102286103cc3660046129a5565b610f8d565b6013546101ff565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b61041261040d366004612acc565b611358565b604080519283526020830191909152016101e3565b610228610435366004612bff565b611449565b610228610448366004612c4b565b611551565b7f00000000000000000000000000000000000000000000000000000000000000006101ff565b610228610481366004612ce4565b6116cb565b6101ff610494366004612768565b60006020819052908152604090205481565b601381815481106104b657600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061052e9060601c63ffffffff1690565b63ffffffff16905060005b601081101561061b57816001166001036105c15773ffffffffffffffffffffffffffffffffffffffff851660009081526014602090815260408083208784529091529020816010811061058e5761058e612d20565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610602565b82600382601081106105d5576105d5612d20565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061061381612d7e565b915050610539565b505092915050565b600061062f8a8a6104eb565b905061065286868360208b013561064d6106488d612db6565b6118de565b61191e565b80156106705750610670838383602088013561064d6106488a612db6565b6106a6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8660400135886040516020016106bc9190612e85565b6040516020818303038152906040528051906020012014610709576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161071f9190612ec3565b14610756576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61079e886107648680612edb565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197f92505050565b6107a788611ada565b8360400135886040516020016107bd9190612e85565b604051602081830303815290604052805190602001200361080a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9590951660009081526015602090815260408083209683529590529390932080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550505050565b600161087f60106002613062565b610889919061306e565b81565b60006108988686612376565b90506108a5836008612ec3565b8211806108b25750602083115b156108e9576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6060811561097a576109738686612423565b90506109b4565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b8154815260200190600101908083116109e157505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610a628260601c63ffffffff1690565b63ffffffff169050333214610aa3576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ab38260801c63ffffffff1690565b63ffffffff16600003610af2576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610afc8260c01c90565b67ffffffffffffffff1615610b3d576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610b76576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8389898d88866124ac565b83516020850160888204881415608883061715610ba8576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610c58578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610c4d576001821615610c2d5782818b0152610c4d565b8981015160009081526020938452604090209260019290921c9101610c10565b505050608801610bb5565b50505050600160106002610c6c9190613062565b610c76919061306e565b811115610caf576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d24610cc28360401c63ffffffff1690565b610cd29063ffffffff168a612ec3565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b91508415610d4f5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791505b3360009081526014602090815260408083208e84529091529020610d75908460106126de565b50503360008181526017602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b60038160108110610dff57600080fd5b0154905081565b60176020528260005260406000206020528160005260406000208181548110610e2e57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b604435600080600883018610610e7e5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa905080610eab57600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b60146020528260005260406000206020528160005260406000208160108110610f8357600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff811615611000576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061102b8260c01c90565b61103f9067ffffffffffffffff164261306e565b11611076576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110828b8b6104eb565b905061109b87878360208c013561064d6106488e612db6565b80156110b957506110b9848483602089013561064d6106488b612db6565b6110ef576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016111059190612e85565b6040516020818303038152906040528051906020012014611152576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460200135886020013560016111689190612ec3565b14158061119a575060016111828360601c63ffffffff1690565b61118c9190613085565b63ffffffff16856020013514155b156111d1576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111e38360801c63ffffffff1690565b63ffffffff169050806111fc8460401c63ffffffff1690565b63ffffffff1614611239576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112478a6107648880612edb565b6112508a611ada565b600061125b8b6125ff565b9050600061126f8560a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601660008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008e8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555082600080848152602001908152602001600020819055505050505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166113e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546113fd816008612ec3565b611408856020612ec3565b106114265783611419826008612ec3565b611423919061306e565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186106114675763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b600061155d86866104eb565b9050611576838383602088013561064d6106488a612db6565b6115ac576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840135156115e8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115f061271c565b6115fe816107648780612edb565b61160781611ada565b84604001358160405160200161161d9190612e85565b604051602081830303815290604052805190602001200361166a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9290921660009081526015602090815260408083209383529290522080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550565b333214611704576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61170f8160086130aa565b63ffffffff168263ffffffff1610611753576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000008163ffffffff1610156117b3576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b9490941790945582518084019093529082529181019283526013805460018101825592525160029091027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093169290921790915590517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09190910155565b6000816000015182602001518360400151604051602001611901939291906130d2565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611972578060051b880135600186831c16600181146119575760008481526020839052604090209350611968565b600082815260208590526040902093505b5050600101611924565b5090931495945050505050565b608881511461198d57600080fd5b6020810160208301611a0e565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050611a08816119f3868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b611a1a6000838361199a565b611a266001838361199a565b611a326002838361199a565b611a3e6003838361199a565b611a4a6004838361199a565b611a566005838361199a565b611a626006838361199a565b611a6e6007838361199a565b611a7a6008838361199a565b611a866009838361199a565b611a92600a838361199a565b611a9e600b838361199a565b611aaa600c838361199a565b611ab6600d838361199a565b611ac2600e838361199a565b611ace600f838361199a565b611a086010838361199a565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612256565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c611c8d8660011b67ffffffffffffffff1690565b18188584603f1c611ca88660011b67ffffffffffffffff1690565b18188584603f1c611cc38660011b67ffffffffffffffff1690565b181895508483603f1c611ce08560011b67ffffffffffffffff1690565b181894508387603f1c611cfd8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525050505050565b61207d81611bd0565b805160208201805160408401805160608601805160808801805167ffffffffffffffff871986168a188116808c528619851689188216909952831982169095188516909552841988169091188316909152941990921618811690925260a08301805160c0808601805160e0880180516101008a0180516101208c018051861985168a188d16909a528319821686188c16909652801989169092188a169092528619861618881690529219909216909218841690526101408401805161016086018051610180880180516101a08a0180516101c08c0180518619851689188d169099528319821686188c16909652801988169092188a169092528519851618881690529119909116909118841690526101e08401805161020086018051610220880180516102408a0180516102608c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052610280840180516102a0860180516102c0880180516102e08a0180516103008c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052600386901b850151901c9081189091168252611a08565b61226260008284612074565b61226e60018284612074565b61227a60028284612074565b61228660038284612074565b61229260048284612074565b61229e60058284612074565b6122aa60068284612074565b6122b660078284612074565b6122c260088284612074565b6122ce60098284612074565b6122da600a8284612074565b6122e6600b8284612074565b6122f2600c8284612074565b6122fe600d8284612074565b61230a600e8284612074565b612316600f8284612074565b61232260108284612074565b61232e60118284612074565b61233a60128284612074565b61234660138284612074565b61235260148284612074565b61235e60158284612074565b61236a60168284612074565b611a0860178284612074565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83161761241c818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612481576088829003850160808582017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01536001845160001a1784538652612493565b60018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b60006124be8260a01c63ffffffff1690565b67ffffffffffffffff16905060006124dc8360801c63ffffffff1690565b63ffffffff16905060006124f68460401c63ffffffff1690565b63ffffffff16905060088310801561250c575080155b156125405760c082901b6000908152883560085283513382526016602090815260408084208a8552909152909120556125f5565b6008831015801561255e57508061255860088561306e565b93508310155b8015612572575061256f8782612ec3565b83105b156125f5576000612583828561306e565b905087612591826020612ec3565b1015801561259d575085155b156125d4576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526016602090815260408083208a845290915290209089013590555b5050505050505050565b6000612682565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff006126308360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff000061265d8360101b67ffffffffffffffff1690565b1617905060008160201c61267b8360201b67ffffffffffffffff1690565b1792915050565b6080820151602083019061269a90612606565b612606565b60408201516126a890612606565b60401b176126c061269560018460059190911b015190565b825160809190911b906126d290612606565b60c01b17179392505050565b826010810192821561270c579160200282015b8281111561270c5782518255916020019190600101906126f1565b50612718929150612734565b5090565b604051806020016040528061272f612749565b905290565b5b808211156127185760008155600101612735565b6040518061032001604052806019906020820280368337509192915050565b60006020828403121561277a57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146127a557600080fd5b919050565b600080604083850312156127bd57600080fd5b6127c683612781565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612827576128276127d4565b60405290565b6040516060810167ffffffffffffffff81118282101715612827576128276127d4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612897576128976127d4565b604052919050565b60006103208083850312156128b357600080fd5b604051602080820167ffffffffffffffff83821081831117156128d8576128d86127d4565b8160405283955087601f8801126128ee57600080fd5b6128f6612803565b948701949150818886111561290a57600080fd5b875b8681101561293257803583811681146129255760008081fd5b845292840192840161290c565b50909352509295945050505050565b60006060828403121561295357600080fd5b50919050565b60008083601f84011261296b57600080fd5b50813567ffffffffffffffff81111561298357600080fd5b6020830191508360208260051b850101111561299e57600080fd5b9250929050565b60008060008060008060008060006103e08a8c0312156129c457600080fd5b6129cd8a612781565b985060208a013597506129e38b60408c0161289f565b96506103608a013567ffffffffffffffff80821115612a0157600080fd5b612a0d8d838e01612941565b97506103808c0135915080821115612a2457600080fd5b612a308d838e01612959565b90975095506103a08c0135915080821115612a4a57600080fd5b612a568d838e01612941565b94506103c08c0135915080821115612a6d57600080fd5b50612a7a8c828d01612959565b915080935050809150509295985092959850929598565b600080600080600060a08688031215612aa957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215612adf57600080fd5b50508035926020909101359150565b60008083601f840112612b0057600080fd5b50813567ffffffffffffffff811115612b1857600080fd5b60208301915083602082850101111561299e57600080fd5b600080600080600080600060a0888a031215612b4b57600080fd5b8735965060208801359550604088013567ffffffffffffffff80821115612b7157600080fd5b612b7d8b838c01612aee565b909750955060608a0135915080821115612b9657600080fd5b50612ba38a828b01612959565b90945092505060808801358015158114612bbc57600080fd5b8091505092959891949750929550565b600080600060608486031215612be157600080fd5b612bea84612781565b95602085013595506040909401359392505050565b600080600060408486031215612c1457600080fd5b83359250602084013567ffffffffffffffff811115612c3257600080fd5b612c3e86828701612aee565b9497909650939450505050565b600080600080600060808688031215612c6357600080fd5b612c6c86612781565b945060208601359350604086013567ffffffffffffffff80821115612c9057600080fd5b612c9c89838a01612941565b94506060880135915080821115612cb257600080fd5b50612cbf88828901612959565b969995985093965092949392505050565b803563ffffffff811681146127a557600080fd5b600080600060608486031215612cf957600080fd5b83359250612d0960208501612cd0565b9150612d1760408501612cd0565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612daf57612daf612d4f565b5060010190565b600060608236031215612dc857600080fd5b612dd061282d565b823567ffffffffffffffff80821115612de857600080fd5b9084019036601f830112612dfb57600080fd5b8135602082821115612e0f57612e0f6127d4565b612e3f817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612850565b92508183523681838601011115612e5557600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b6019811015612eba57825167ffffffffffffffff16825260209283019290910190600101612e91565b50505092915050565b60008219821115612ed657612ed6612d4f565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f1057600080fd5b83018035915067ffffffffffffffff821115612f2b57600080fd5b60200191503681900382131561299e57600080fd5b600181815b80851115612f9957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612f7f57612f7f612d4f565b80851615612f8c57918102915b93841c9390800290612f45565b509250929050565b600082612fb05750600161305c565b81612fbd5750600061305c565b8160018114612fd35760028114612fdd57612ff9565b600191505061305c565b60ff841115612fee57612fee612d4f565b50506001821b61305c565b5060208310610133831016604e8410600b841016171561301c575081810a61305c565b6130268383612f40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561305857613058612d4f565b0290505b92915050565b600061241c8383612fa1565b60008282101561308057613080612d4f565b500390565b600063ffffffff838116908316818110156130a2576130a2612d4f565b039392505050565b600063ffffffff8083168185168083038211156130c9576130c9612d4f565b01949350505050565b6000845160005b818110156130f357602081880181015185830152016130d9565b81811115613102576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a00000000000000000000000000000000000000000000000000000000001b77400000000000000000000000000000000000000000000000000000000000015180

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101a35760003560e01c80638dc4be11116100ee578063dd24f9bf11610097578063ec5efcbc11610071578063ec5efcbc1461043a578063f3f480d91461044d578063faf37bc714610473578063fef2b4ed1461048657600080fd5b8063dd24f9bf146103d9578063e03110e1146103ff578063e15926111461042757600080fd5b8063b4801e61116100c8578063b4801e61146103ab578063d18534b5146103be578063da35c664146103d157600080fd5b80638dc4be111461032b5780639d53a6481461033e578063b2e67ba81461038057600080fd5b806361238bde116101505780637ac547671161012a5780637ac54767146102ae5780638542cf50146102c1578063882856ef146102ff57600080fd5b806361238bde146102455780636551927b146102705780637917de1d1461029b57600080fd5b80633909af5c116101815780633909af5c146102155780634d52b4c91461022a57806352f0f3ad1461023257600080fd5b8063013cf08b146101a85780630359a563146101ec5780632055b36b1461020d575b600080fd5b6101bb6101b6366004612768565b6104a6565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526020830191909152015b60405180910390f35b6101ff6101fa3660046127aa565b6104eb565b6040519081526020016101e3565b6101ff601081565b6102286102233660046129a5565b610623565b005b6101ff610871565b6101ff610240366004612a91565b61088c565b6101ff610253366004612acc565b600160209081526000928352604080842090915290825290205481565b6101ff61027e3660046127aa565b601560209081526000928352604080842090915290825290205481565b6102286102a9366004612b30565b610961565b6101ff6102bc366004612768565b610def565b6102ef6102cf366004612acc565b600260209081526000928352604080842090915290825290205460ff1681565b60405190151581526020016101e3565b61031261030d366004612bcc565b610e06565b60405167ffffffffffffffff90911681526020016101e3565b610228610339366004612bff565b610e60565b6101ff61034c3660046127aa565b73ffffffffffffffffffffffffffffffffffffffff9091166000908152601760209081526040808320938352929052205490565b6101ff61038e3660046127aa565b601660209081526000928352604080842090915290825290205481565b6101ff6103b9366004612bcc565b610f5b565b6102286103cc3660046129a5565b610f8d565b6013546101ff565b7f00000000000000000000000000000000000000000000000000000000001b77406101ff565b61041261040d366004612acc565b611358565b604080519283526020830191909152016101e3565b610228610435366004612bff565b611449565b610228610448366004612c4b565b611551565b7f00000000000000000000000000000000000000000000000000000000000151806101ff565b610228610481366004612ce4565b6116cb565b6101ff610494366004612768565b60006020819052908152604090205481565b601381815481106104b657600080fd5b60009182526020909120600290910201805460019091015473ffffffffffffffffffffffffffffffffffffffff909116915082565b73ffffffffffffffffffffffffffffffffffffffff82166000908152601560209081526040808320848452909152812054819061052e9060601c63ffffffff1690565b63ffffffff16905060005b601081101561061b57816001166001036105c15773ffffffffffffffffffffffffffffffffffffffff851660009081526014602090815260408083208784529091529020816010811061058e5761058e612d20565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250610602565b82600382601081106105d5576105d5612d20565b01546040805160208101939093528201526060016040516020818303038152906040528051906020012092505b60019190911c908061061381612d7e565b915050610539565b505092915050565b600061062f8a8a6104eb565b905061065286868360208b013561064d6106488d612db6565b6118de565b61191e565b80156106705750610670838383602088013561064d6106488a612db6565b6106a6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8660400135886040516020016106bc9190612e85565b6040516020818303038152906040528051906020012014610709576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83602001358760200135600161071f9190612ec3565b14610756576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61079e886107648680612edb565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197f92505050565b6107a788611ada565b8360400135886040516020016107bd9190612e85565b604051602081830303815290604052805190602001200361080a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9590951660009081526015602090815260408083209683529590529390932080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550505050565b600161087f60106002613062565b610889919061306e565b81565b60006108988686612376565b90506108a5836008612ec3565b8211806108b25750602083115b156108e9576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000602081815260c085901b82526008959095528251828252600286526040808320858452875280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558484528752808320948352938652838220558181529384905292205592915050565b6060811561097a576109738686612423565b90506109b4565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050505b3360009081526014602090815260408083208b845290915280822081516102008101928390529160109082845b8154815260200190600101908083116109e157505050505090506000601560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008b81526020019081526020016000205490506000610a628260601c63ffffffff1690565b63ffffffff169050333214610aa3576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ab38260801c63ffffffff1690565b63ffffffff16600003610af2576040517f87138d5c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610afc8260c01c90565b67ffffffffffffffff1615610b3d576040517f475a253500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b898114610b76576040517f60f95d5a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b8389898d88866124ac565b83516020850160888204881415608883061715610ba8576307b1daf16000526004601cfd5b60405160c8810160405260005b83811015610c58578083018051835260208101516020840152604081015160408401526060810151606084015260808101516080840152508460888301526088810460051b8b013560a883015260c882206001860195508560005b610200811015610c4d576001821615610c2d5782818b0152610c4d565b8981015160009081526020938452604090209260019290921c9101610c10565b505050608801610bb5565b50505050600160106002610c6c9190613062565b610c76919061306e565b811115610caf576040517f6229572300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d24610cc28360401c63ffffffff1690565b610cd29063ffffffff168a612ec3565b60401b7fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff606084901b167fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8516171790565b91508415610d4f5777ffffffffffffffffffffffffffffffffffffffffffffffff82164260c01b1791505b3360009081526014602090815260408083208e84529091529020610d75908460106126de565b50503360008181526017602090815260408083208e8452825280832080546001810182559084528284206004820401805460039092166008026101000a67ffffffffffffffff818102199093164390931602919091179055928252601581528282209c82529b909b52909920989098555050505050505050565b60038160108110610dff57600080fd5b0154905081565b60176020528260005260406000206020528160005260406000208181548110610e2e57600080fd5b906000526020600020906004918282040191900660080292509250509054906101000a900467ffffffffffffffff1681565b604435600080600883018610610e7e5763fe2549876000526004601cfd5b60c083901b60805260888386823786600882030151915060206000858360025afa905080610eab57600080fd5b50600080517effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0400000000000000000000000000000000000000000000000000000000000000178082526002602090815260408084208a8552825280842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091558385528252808420998452988152888320939093558152908190529490942055505050565b60146020528260005260406000206020528160005260406000208160108110610f8357600080fd5b0154925083915050565b73ffffffffffffffffffffffffffffffffffffffff891660009081526015602090815260408083208b845290915290205467ffffffffffffffff811615611000576040517fc334f06900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000001518061102b8260c01c90565b61103f9067ffffffffffffffff164261306e565b11611076576040517f55d4cbf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110828b8b6104eb565b905061109b87878360208c013561064d6106488e612db6565b80156110b957506110b9848483602089013561064d6106488b612db6565b6110ef576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8760400135896040516020016111059190612e85565b6040516020818303038152906040528051906020012014611152576040517f1968a90200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460200135886020013560016111689190612ec3565b14158061119a575060016111828360601c63ffffffff1690565b61118c9190613085565b63ffffffff16856020013514155b156111d1576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111e38360801c63ffffffff1690565b63ffffffff169050806111fc8460401c63ffffffff1690565b63ffffffff1614611239576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112478a6107648880612edb565b6112508a611ada565b600061125b8b6125ff565b9050600061126f8560a01c63ffffffff1690565b67ffffffffffffffff169050600160026000848152602001908152602001600020600083815260200190815260200160002060006101000a81548160ff021916908315150217905550601660008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008e8152602001908152602001600020546001600084815260200190815260200160002060008381526020019081526020016000208190555082600080848152602001908152602001600020819055505050505050505050505050505050565b6000828152600260209081526040808320848452909152812054819060ff166113e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f7072652d696d616765206d757374206578697374000000000000000000000000604482015260640160405180910390fd5b50600083815260208181526040909120546113fd816008612ec3565b611408856020612ec3565b106114265783611419826008612ec3565b611423919061306e565b91505b506000938452600160209081526040808620948652939052919092205492909150565b6044356000806008830186106114675763fe2549876000526004601cfd5b60c083901b6080526088838682378087017ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80151908490207effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f02000000000000000000000000000000000000000000000000000000000000001760008181526002602090815260408083208b8452825280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915584845282528083209a83529981528982209390935590815290819052959095209190915550505050565b600061155d86866104eb565b9050611576838383602088013561064d6106488a612db6565b6115ac576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020840135156115e8576040517f9a3b119900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6115f061271c565b6115fe816107648780612edb565b61160781611ada565b84604001358160405160200161161d9190612e85565b604051602081830303815290604052805190602001200361166a576040517f9843145b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505073ffffffffffffffffffffffffffffffffffffffff9290921660009081526015602090815260408083209383529290522080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016600117905550565b333214611704576040517fba092d1600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61170f8160086130aa565b63ffffffff168263ffffffff1610611753576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000001b77408163ffffffff1610156117b3576040517f7b1dafd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000818152601560209081526040808320878452825280832080547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1660a09790971b7fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff169690961760809590951b9490941790945582518084019093529082529181019283526013805460018101825592525160029091027f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a0908101805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff00000000000000000000000000000000000000009093169290921790915590517f66de8ffda797e3de9c05e8fc57b3bf0ec28a930d40b0d285d93c06501cf6a09190910155565b6000816000015182602001518360400151604051602001611901939291906130d2565b604051602081830303815290604052805190602001209050919050565b60008160005b6010811015611972578060051b880135600186831c16600181146119575760008481526020839052604090209350611968565b600082815260208590526040902093505b5050600101611924565b5090931495945050505050565b608881511461198d57600080fd5b6020810160208301611a0e565b8260031b8201518060001a8160011a60081b178160021a60101b8260031a60181b17178160041a60201b8260051a60281b178260061a60301b8360071a60381b1717179050611a08816119f3868560059190911b015190565b1867ffffffffffffffff16600586901b840152565b50505050565b611a1a6000838361199a565b611a266001838361199a565b611a326002838361199a565b611a3e6003838361199a565b611a4a6004838361199a565b611a566005838361199a565b611a626006838361199a565b611a6e6007838361199a565b611a7a6008838361199a565b611a866009838361199a565b611a92600a838361199a565b611a9e600b838361199a565b611aaa600c838361199a565b611ab6600d838361199a565b611ac2600e838361199a565b611ace600f838361199a565b611a086010838361199a565b6040805178010000000000008082800000000000808a8000000080008000602082015279808b00000000800000018000000080008081800000000000800991810191909152788a00000000000000880000000080008009000000008000000a60608201527b8000808b800000000000008b8000000000008089800000000000800360808201527f80000000000080028000000000000080000000000000800a800000008000000a60a08201527f800000008000808180000000000080800000000080000001800000008000800860c082015260009060e00160405160208183030381529060405290506020820160208201612256565b6102808101516101e082015161014083015160a0840151845118189118186102a082015161020083015161016084015160c0850151602086015118189118186102c083015161022084015161018085015160e0860151604087015118189118186102e08401516102408501516101a0860151610100870151606088015118189118186103008501516102608601516101c0870151610120880151608089015118189118188084603f1c611c8d8660011b67ffffffffffffffff1690565b18188584603f1c611ca88660011b67ffffffffffffffff1690565b18188584603f1c611cc38660011b67ffffffffffffffff1690565b181895508483603f1c611ce08560011b67ffffffffffffffff1690565b181894508387603f1c611cfd8960011b67ffffffffffffffff1690565b60208b01518b51861867ffffffffffffffff168c5291189190911897508118600181901b603f9190911c18935060c08801518118601481901c602c9190911b1867ffffffffffffffff1660208901526101208801518718602c81901c60149190911b1867ffffffffffffffff1660c08901526102c08801518618600381901c603d9190911b1867ffffffffffffffff166101208901526101c08801518718601981901c60279190911b1867ffffffffffffffff166102c08901526102808801518218602e81901c60129190911b1867ffffffffffffffff166101c089015260408801518618600281901c603e9190911b1867ffffffffffffffff166102808901526101808801518618601581901c602b9190911b1867ffffffffffffffff1660408901526101a08801518518602781901c60199190911b1867ffffffffffffffff166101808901526102608801518718603881901c60089190911b1867ffffffffffffffff166101a08901526102e08801518518600881901c60389190911b1867ffffffffffffffff166102608901526101e08801518218601781901c60299190911b1867ffffffffffffffff166102e089015260808801518718602581901c601b9190911b1867ffffffffffffffff166101e08901526103008801518718603281901c600e9190911b1867ffffffffffffffff1660808901526102a08801518118603e81901c60029190911b1867ffffffffffffffff166103008901526101008801518518600981901c60379190911b1867ffffffffffffffff166102a08901526102008801518118601381901c602d9190911b1867ffffffffffffffff1661010089015260a08801518218601c81901c60249190911b1867ffffffffffffffff1661020089015260608801518518602481901c601c9190911b1867ffffffffffffffff1660a08901526102408801518518602b81901c60159190911b1867ffffffffffffffff1660608901526102208801518618603181901c600f9190911b1867ffffffffffffffff166102408901526101608801518118603681901c600a9190911b1867ffffffffffffffff166102208901525060e08701518518603a81901c60069190911b1867ffffffffffffffff166101608801526101408701518118603d81901c60039190911b1867ffffffffffffffff1660e0880152505067ffffffffffffffff81166101408601525050505050565b61207d81611bd0565b805160208201805160408401805160608601805160808801805167ffffffffffffffff871986168a188116808c528619851689188216909952831982169095188516909552841988169091188316909152941990921618811690925260a08301805160c0808601805160e0880180516101008a0180516101208c018051861985168a188d16909a528319821686188c16909652801989169092188a169092528619861618881690529219909216909218841690526101408401805161016086018051610180880180516101a08a0180516101c08c0180518619851689188d169099528319821686188c16909652801988169092188a169092528519851618881690529119909116909118841690526101e08401805161020086018051610220880180516102408a0180516102608c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052610280840180516102a0860180516102c0880180516102e08a0180516103008c0180518619851689188d169099528319821686188c16909652801988169092188a16909252851985161888169052911990911690911884169052600386901b850151901c9081189091168252611a08565b61226260008284612074565b61226e60018284612074565b61227a60028284612074565b61228660038284612074565b61229260048284612074565b61229e60058284612074565b6122aa60068284612074565b6122b660078284612074565b6122c260088284612074565b6122ce60098284612074565b6122da600a8284612074565b6122e6600b8284612074565b6122f2600c8284612074565b6122fe600d8284612074565b61230a600e8284612074565b612316600f8284612074565b61232260108284612074565b61232e60118284612074565b61233a60128284612074565b61234660138284612074565b61235260148284612074565b61235e60158284612074565b61236a60168284612074565b611a0860178284612074565b7f01000000000000000000000000000000000000000000000000000000000000007effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83161761241c818360408051600093845233602052918152606090922091527effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01000000000000000000000000000000000000000000000000000000000000001790565b9392505050565b6060604051905081602082018181018286833760888306808015612481576088829003850160808582017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01536001845160001a1784538652612493565b60018353608060878401536088850186525b5050505050601f19603f82510116810160405292915050565b60006124be8260a01c63ffffffff1690565b67ffffffffffffffff16905060006124dc8360801c63ffffffff1690565b63ffffffff16905060006124f68460401c63ffffffff1690565b63ffffffff16905060088310801561250c575080155b156125405760c082901b6000908152883560085283513382526016602090815260408084208a8552909152909120556125f5565b6008831015801561255e57508061255860088561306e565b93508310155b8015612572575061256f8782612ec3565b83105b156125f5576000612583828561306e565b905087612591826020612ec3565b1015801561259d575085155b156125d4576040517ffe25498700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360009081526016602090815260408083208a845290915290209089013590555b5050505050505050565b6000612682565b66ff00ff00ff00ff8160081c1667ff00ff00ff00ff006126308360081b67ffffffffffffffff1690565b1617905065ffff0000ffff8160101c1667ffff0000ffff000061265d8360101b67ffffffffffffffff1690565b1617905060008160201c61267b8360201b67ffffffffffffffff1690565b1792915050565b6080820151602083019061269a90612606565b612606565b60408201516126a890612606565b60401b176126c061269560018460059190911b015190565b825160809190911b906126d290612606565b60c01b17179392505050565b826010810192821561270c579160200282015b8281111561270c5782518255916020019190600101906126f1565b50612718929150612734565b5090565b604051806020016040528061272f612749565b905290565b5b808211156127185760008155600101612735565b6040518061032001604052806019906020820280368337509192915050565b60006020828403121561277a57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146127a557600080fd5b919050565b600080604083850312156127bd57600080fd5b6127c683612781565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610320810167ffffffffffffffff81118282101715612827576128276127d4565b60405290565b6040516060810167ffffffffffffffff81118282101715612827576128276127d4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612897576128976127d4565b604052919050565b60006103208083850312156128b357600080fd5b604051602080820167ffffffffffffffff83821081831117156128d8576128d86127d4565b8160405283955087601f8801126128ee57600080fd5b6128f6612803565b948701949150818886111561290a57600080fd5b875b8681101561293257803583811681146129255760008081fd5b845292840192840161290c565b50909352509295945050505050565b60006060828403121561295357600080fd5b50919050565b60008083601f84011261296b57600080fd5b50813567ffffffffffffffff81111561298357600080fd5b6020830191508360208260051b850101111561299e57600080fd5b9250929050565b60008060008060008060008060006103e08a8c0312156129c457600080fd5b6129cd8a612781565b985060208a013597506129e38b60408c0161289f565b96506103608a013567ffffffffffffffff80821115612a0157600080fd5b612a0d8d838e01612941565b97506103808c0135915080821115612a2457600080fd5b612a308d838e01612959565b90975095506103a08c0135915080821115612a4a57600080fd5b612a568d838e01612941565b94506103c08c0135915080821115612a6d57600080fd5b50612a7a8c828d01612959565b915080935050809150509295985092959850929598565b600080600080600060a08688031215612aa957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215612adf57600080fd5b50508035926020909101359150565b60008083601f840112612b0057600080fd5b50813567ffffffffffffffff811115612b1857600080fd5b60208301915083602082850101111561299e57600080fd5b600080600080600080600060a0888a031215612b4b57600080fd5b8735965060208801359550604088013567ffffffffffffffff80821115612b7157600080fd5b612b7d8b838c01612aee565b909750955060608a0135915080821115612b9657600080fd5b50612ba38a828b01612959565b90945092505060808801358015158114612bbc57600080fd5b8091505092959891949750929550565b600080600060608486031215612be157600080fd5b612bea84612781565b95602085013595506040909401359392505050565b600080600060408486031215612c1457600080fd5b83359250602084013567ffffffffffffffff811115612c3257600080fd5b612c3e86828701612aee565b9497909650939450505050565b600080600080600060808688031215612c6357600080fd5b612c6c86612781565b945060208601359350604086013567ffffffffffffffff80821115612c9057600080fd5b612c9c89838a01612941565b94506060880135915080821115612cb257600080fd5b50612cbf88828901612959565b969995985093965092949392505050565b803563ffffffff811681146127a557600080fd5b600080600060608486031215612cf957600080fd5b83359250612d0960208501612cd0565b9150612d1760408501612cd0565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203612daf57612daf612d4f565b5060010190565b600060608236031215612dc857600080fd5b612dd061282d565b823567ffffffffffffffff80821115612de857600080fd5b9084019036601f830112612dfb57600080fd5b8135602082821115612e0f57612e0f6127d4565b612e3f817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601612850565b92508183523681838601011115612e5557600080fd5b81818501828501376000918301810191909152908352848101359083015250604092830135928101929092525090565b81516103208201908260005b6019811015612eba57825167ffffffffffffffff16825260209283019290910190600101612e91565b50505092915050565b60008219821115612ed657612ed6612d4f565b500190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f1057600080fd5b83018035915067ffffffffffffffff821115612f2b57600080fd5b60200191503681900382131561299e57600080fd5b600181815b80851115612f9957817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115612f7f57612f7f612d4f565b80851615612f8c57918102915b93841c9390800290612f45565b509250929050565b600082612fb05750600161305c565b81612fbd5750600061305c565b8160018114612fd35760028114612fdd57612ff9565b600191505061305c565b60ff841115612fee57612fee612d4f565b50506001821b61305c565b5060208310610133831016604e8410600b841016171561301c575081810a61305c565b6130268383612f40565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561305857613058612d4f565b0290505b92915050565b600061241c8383612fa1565b60008282101561308057613080612d4f565b500390565b600063ffffffff838116908316818110156130a2576130a2612d4f565b039392505050565b600063ffffffff8083168185168083038211156130c9576130c9612d4f565b01949350505050565b6000845160005b818110156130f357602081880181015185830152016130d9565b81811115613102576000828501525b509190910192835250602082015260400191905056fea164736f6c634300080f000a

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

00000000000000000000000000000000000000000000000000000000001b77400000000000000000000000000000000000000000000000000000000000015180

-----Decoded View---------------
Arg [0] : _minProposalSize (uint256): 1800000
Arg [1] : _challengePeriod (uint256): 86400

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000001b7740
Arg [1] : 0000000000000000000000000000000000000000000000000000000000015180


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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