ETH Price: $2,948.39 (+1.23%)

Contract

0xa2703b8dd14F50D17F2517327797Bce292D00E1E

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
385067742026-01-24 11:45:332 hrs ago1769255133  Contract Creation0 ETH

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SP1Beefy

Compiler Version
v0.8.30+commit.73712a01

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion
// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.20;

import {IConsensus, IntermediateState} from "@hyperbridge/core/interfaces/IConsensus.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {ISP1Verifier} from "@sp1-contracts/ISP1Verifier.sol";

import "./Codec.sol";
import "./Types.sol";

/**
 * @title The SP1 BEEFY Consensus Client.
 * @author Polytope Labs ([email protected])
 *
 * @notice Similar to the BeefyV1 client but delegates secp256k1 signature verification, authority set membership proof checks
 * and mmr leaf to an SP1 program.
 */
contract SP1Beefy is IConsensus, ERC165 {
    using HeaderImpl for Header;

    // SP1 verification key
    bytes32 public immutable _verificationKey;

    // Sp1 verifier contract
    ISP1Verifier public immutable _verifier;

    // Provided authority set id was unknown
    error UnknownAuthoritySet();

    // Provided consensus proof height is stale
    error StaleHeight();

    // Genesis block should not be provided
    error IllegalGenesisBlock();

    constructor(ISP1Verifier verifier, bytes32 verificationKey) {
        _verifier = verifier;
        _verificationKey = verificationKey;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IConsensus).interfaceId || super.supportsInterface(interfaceId);
    }

    /*
     * @dev Given some opaque consensus proof, produce the new consensus state and newly finalized intermediate states.
     */
    function verifyConsensus(bytes calldata encodedState, bytes calldata encodedProof)
        external
        view
        returns (bytes memory, IntermediateState[] memory)
    {
        BeefyConsensusState memory consensusState = abi.decode(encodedState, (BeefyConsensusState));
        (
            MiniCommitment memory commitment,
            PartialBeefyMmrLeaf memory leaf,
            ParachainHeader[] memory headers,
            bytes memory plonkProof
        ) = abi.decode(encodedProof, (MiniCommitment, PartialBeefyMmrLeaf, ParachainHeader[], bytes));
        SP1BeefyProof memory proof =
            SP1BeefyProof({commitment: commitment, mmrLeaf: leaf, headers: headers, proof: plonkProof});

        (BeefyConsensusState memory newState, IntermediateState[] memory intermediates) =
            verifyConsensus(consensusState, proof);

        return (abi.encode(newState), intermediates);
    }

    /**
     * @dev Verifies an SP1 proof of consensus.
     */
    function verifyConsensus(BeefyConsensusState memory trustedState, SP1BeefyProof memory proof)
        internal
        view
        returns (BeefyConsensusState memory, IntermediateState[] memory)
    {
        MiniCommitment memory commitment = proof.commitment;
        if (trustedState.latestHeight >= commitment.blockNumber) revert StaleHeight();

        AuthoritySetCommitment memory authority;
        if (commitment.validatorSetId == trustedState.nextAuthoritySet.id) {
            authority = trustedState.nextAuthoritySet;
        } else if (commitment.validatorSetId == trustedState.currentAuthoritySet.id) {
            authority = trustedState.currentAuthoritySet;
        } else {
            revert UnknownAuthoritySet();
        }

        uint256 headers_len = proof.headers.length;
        bytes32[] memory headers = new bytes32[](headers_len);
        for (uint256 i = 0; i < headers_len; i++) {
            headers[i] = keccak256(proof.headers[i].header);
        }

        bytes memory publicInputs = abi.encode(
            PublicInputs({
                authorities_len: authority.len,
                authorities_root: authority.root,
                headers: headers,
                leaf_hash: keccak256(Codec.Encode(proof.mmrLeaf))
            })
        );

        _verifier.verifyProof(_verificationKey, publicInputs, proof.proof);

        uint256 statesLen = proof.headers.length;
        IntermediateState[] memory intermediates = new IntermediateState[](statesLen);
        for (uint256 i = 0; i < statesLen; i++) {
            ParachainHeader memory para = proof.headers[i];
            Header memory header = Codec.DecodeHeader(para.header);
            if (header.number == 0) revert IllegalGenesisBlock();
            StateCommitment memory stateCommitment = header.stateCommitment();
            IntermediateState memory intermediate =
                IntermediateState({stateMachineId: para.id, height: header.number, commitment: stateCommitment});
            intermediates[i] = intermediate;
        }

        if (proof.mmrLeaf.nextAuthoritySet.id > trustedState.nextAuthoritySet.id) {
            trustedState.currentAuthoritySet = trustedState.nextAuthoritySet;
            trustedState.nextAuthoritySet = proof.mmrLeaf.nextAuthoritySet;
        }

        trustedState.latestHeight = commitment.blockNumber;

        return (trustedState, intermediates);
    }

    // @dev so these structs are included in the abi
    function noOp(SP1BeefyProof memory s, PublicInputs memory p) external pure {}
}

// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.17;

/**
 * @title StateCommitment
 * @notice Represents a commitment to an intermediate state in the state machine
 * @dev Contains metadata about the state machine including timestamp and merkle roots
 */
struct StateCommitment {
    /// @notice Unix timestamp of the state machine at the time of this commitment
    /// @dev Used for calculating request timeouts and enforcing time-based logic
    uint256 timestamp;
    /// @notice Merkle root of the overlay trie containing all ISMP requests and responses
    /// @dev Used to verify inclusion proofs for cross-chain messages
    bytes32 overlayRoot;
    /// @notice Merkle root of the state trie at the given block height
    /// @dev Represents the complete state of the state machine at this height
    bytes32 stateRoot;
}

/**
 * @title StateMachineHeight
 * @notice Uniquely identifies a specific height in a state machine
 * @dev Consensus clients may track multiple concurrent state machines, hence the need for an identifier
 */
struct StateMachineHeight {
    /// @notice Unique identifier for the state machine (e.g., parachain ID, chain ID)
    /// @dev Each blockchain or parachain in the network has a unique identifier
    uint256 stateMachineId;
    /// @notice Block height or number in the state machine
    /// @dev Represents the sequential position in the blockchain
    uint256 height;
}

/**
 * @title IntermediateState
 * @notice Represents an intermediate state in the state transition sequence of a state machine
 * @dev Used to track finalized states that have been verified through consensus
 */
struct IntermediateState {
    /// @notice Unique identifier for the state machine
    /// @dev Same as StateMachineHeight.stateMachineId
    uint256 stateMachineId;
    /// @notice Block height of this intermediate state
    /// @dev The specific height at which this state was committed
    uint256 height;
    /// @notice The state commitment at this height
    /// @dev Contains the timestamp and merkle roots for this state
    StateCommitment commitment;
}

/**
 * @title IConsensus
 * @author Polytope Labs ([email protected])
 * @notice Interface for consensus verification in the Hyperbridge protocol
 * @dev Consensus clients implement this interface to verify state transitions from different chains.
 * The internals are intentionally opaque to the ISMP framework, allowing consensus mechanisms
 * to evolve independently (e.g., GRANDPA for Polkadot, Sync Committee for Ethereum).
 * Different consensus mechanisms can be plugged in as long as they conform to this interface.
 */
interface IConsensus {
    /**
     * @notice Verifies a consensus proof and returns the updated consensus state
     * @dev This function is called by the Handler to verify incoming consensus updates.
     * The implementation details vary based on the consensus mechanism being verified.
     * @param trustedState The current trusted consensus state (encoded based on consensus type)
     * @param proof The consensus proof to be verified (e.g., validator signatures, merkle proofs)
     * @return The new consensus state after verification (encoded)
     * @return Array of newly finalized intermediate states that can be trusted
     */
    function verifyConsensus(bytes memory trustedState, bytes memory proof)
        external
        returns (bytes memory, IntermediateState[] memory);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// @title SP1 Verifier Interface
/// @author Succinct Labs
/// @notice This contract is the interface for the SP1 Verifier.
interface ISP1Verifier {
    /// @notice Verifies a proof with given public values and vkey.
    /// @dev It is expected that the first 4 bytes of proofBytes must match the first 4 bytes of
    /// target verifier's VERIFIER_HASH.
    /// @param programVKey The verification key for the RISC-V program.
    /// @param publicValues The public values encoded as bytes.
    /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes.
    function verifyProof(
        bytes32 programVKey,
        bytes calldata publicValues,
        bytes calldata proofBytes
    ) external view;
}

interface ISP1VerifierWithHash is ISP1Verifier {
    /// @notice Returns the hash of the verifier.
    function VERIFIER_HASH() external pure returns (bytes32);
}

// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.17;

import "@polytope-labs/solidity-merkle-trees/src/trie/substrate/ScaleCodec.sol";
import "@polytope-labs/solidity-merkle-trees/src/trie/Bytes.sol";
import "./Header.sol";
import "./Types.sol";

// @dev type encoding stuff
library Codec {
    uint8 internal constant DIGEST_ITEM_OTHER = 0;
    uint8 internal constant DIGEST_ITEM_CONSENSUS = 4;
    uint8 internal constant DIGEST_ITEM_SEAL = 5;
    uint8 internal constant DIGEST_ITEM_PRERUNTIME = 6;
    uint8 internal constant DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED = 8;

    // @dev SCALE-encodes the BEEFY finality commitment
    function Encode(Commitment memory commitment) internal pure returns (bytes memory) {
        uint256 payloadLen = commitment.payload.length;
        bytes memory accumulator = bytes("");
        for (uint256 i = 0; i < payloadLen; i++) {
            accumulator = bytes.concat(
                abi.encodePacked(commitment.payload[i].id), ScaleCodec.encodeBytes(commitment.payload[i].data)
            );
        }

        bytes memory payload = bytes.concat(ScaleCodec.encodeUintCompact(payloadLen), accumulator);

        bytes memory rest = bytes.concat(
            ScaleCodec.encode32(uint32(commitment.blockNumber)), ScaleCodec.encode64(uint64(commitment.validatorSetId))
        );

        return bytes.concat(payload, rest);
    }

    // @dev SCALE-encodes the BEEFY Mmr leaf
    function Encode(PartialBeefyMmrLeaf memory leaf) internal pure returns (bytes memory) {
        bytes memory first =
            bytes.concat(abi.encodePacked(uint8(leaf.version)), ScaleCodec.encode32(uint32(leaf.parentNumber)));
        bytes memory second =
            bytes.concat(bytes.concat(leaf.parentHash), ScaleCodec.encode64(uint64(leaf.nextAuthoritySet.id)));
        bytes memory third = bytes.concat(
            ScaleCodec.encode32(uint32(leaf.nextAuthoritySet.len)), bytes.concat(leaf.nextAuthoritySet.root)
        );
        return bytes.concat(bytes.concat(first, second), bytes.concat(third, bytes.concat(leaf.extra)));
    }

    // @dev Deserializes a substrate header
    function DecodeHeader(bytes memory encoded) internal pure returns (Header memory) {
        ByteSlice memory slice = ByteSlice(encoded, 0);
        bytes32 parentHash = Bytes.toBytes32(Bytes.read(slice, 32));
        uint256 blockNumber = ScaleCodec.decodeUintCompact(slice);
        bytes32 stateRoot = Bytes.toBytes32(Bytes.read(slice, 32));
        bytes32 extrinsicsRoot = Bytes.toBytes32(Bytes.read(slice, 32));

        uint256 length = ScaleCodec.decodeUintCompact(slice);
        Digest[] memory digests = new Digest[](length);

        for (uint256 i = 0; i < length; i++) {
            uint8 kind = Bytes.readByte(slice);
            Digest memory digest;
            if (kind == DIGEST_ITEM_OTHER) {
                digest.isOther = true;
            } else if (kind == DIGEST_ITEM_CONSENSUS) {
                digest.isConsensus = true;
                digest.consensus = decodeDigestItem(slice);
            } else if (kind == DIGEST_ITEM_SEAL) {
                digest.isSeal = true;
                digest.seal = decodeDigestItem(slice);
            } else if (kind == DIGEST_ITEM_PRERUNTIME) {
                digest.isPreRuntime = true;
                digest.preruntime = decodeDigestItem(slice);
            } else if (kind == DIGEST_ITEM_RUNTIME_ENVIRONMENT_UPDATED) {
                digest.isRuntimeEnvironmentUpdated = true;
            }
            digests[i] = digest;
        }

        return Header(parentHash, blockNumber, stateRoot, extrinsicsRoot, digests);
    }

    function decodeDigestItem(ByteSlice memory slice) internal pure returns (DigestItem memory) {
        bytes4 id = Bytes.toBytes4(read(slice, 4), 0);
        uint256 length = ScaleCodec.decodeUintCompact(slice);
        bytes memory data = Bytes.read(slice, length);
        return DigestItem(id, data);
    }

    function read(ByteSlice memory self, uint256 len) internal pure returns (bytes memory) {
        require(self.offset + len <= self.data.length);
        if (len == 0) {
            return "";
        }
        uint256 addr = Memory.dataPtr(self.data);
        bytes memory slice = Memory.toBytes(addr + self.offset, len);
        self.offset += len;
        return slice;
    }

    function readByte(ByteSlice memory self) internal pure returns (uint8) {
        require(self.offset + 1 <= self.data.length);

        uint8 b = uint8(self.data[self.offset]);
        self.offset += 1;

        return b;
    }

    // @dev Decodes a SCALE encoded compact unsigned integer
    function decodeUintCompact(ByteSlice memory data) internal pure returns (uint256 v) {
        uint8 b = readByte(data); // read the first byte
        uint8 mode = b & 3; // bitwise operation

        uint256 value;
        if (mode == 0) {
            // [0, 63]
            value = b >> 2; // right shift to remove mode bits
        } else if (mode == 1) {
            // [64, 16383]
            uint8 bb = readByte(data); // read the second byte
            uint64 r = bb; // convert to uint64
            r <<= 6; // multiply by * 2^6
            r += b >> 2; // right shift to remove mode bits
            value = r;
        } else if (mode == 2) {
            // [16384, 1073741823]
            uint8 b2 = readByte(data); // read the next 3 bytes
            uint8 b3 = readByte(data);
            uint8 b4 = readByte(data);

            uint32 x1 = uint32(b) | (uint32(b2) << 8); // convert to little endian
            uint32 x2 = x1 | (uint32(b3) << 16);
            uint32 x3 = x2 | (uint32(b4) << 24);

            x3 >>= 2; // remove the last 2 mode bits
            value = uint256(x3);
        } else if (mode == 3) {
            // [1073741824, 4503599627370496]
            uint8 l = (b >> 2) + 4; // remove mode bits
            require(l <= 8, "unexpected prefix decoding Compact<Uint>");
            return ScaleCodec.decodeUint256(read(data, l));
        } else {
            revert("Code should be unreachable");
        }
        return (value);
    }

    // @dev Convert the provided type to a bn254 field element
    function toFieldElements(bytes32 source) internal pure returns (bytes32, bytes32) {
        // is assembly cheaper?
        bytes32 left = bytes32(uint256(uint128(bytes16(source))));
        bytes32 right = bytes32(uint256(uint128(uint256(source))));

        return (left, right);
    }
}

File 6 of 12 : Types.sol
// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.17;

import {Node} from "@polytope-labs/solidity-merkle-trees/src/Types.sol";

struct SP1BeefyProof {
    // BEEFY Commitment message
    MiniCommitment commitment;
    // Latest leaf added to mmr
    PartialBeefyMmrLeaf mmrLeaf;
    // Parachain headers finalized by the commitment
    ParachainHeader[] headers;
    // SP1 plonk proof for BEEFY consensus
    bytes proof;
}

struct MiniCommitment {
    uint256 blockNumber;
    uint256 validatorSetId;
}

struct ParachainHeader {
    /// Parachain Id
    uint256 id;
    /// SCALE encoded header
    bytes header;
}

/// The public values encoded as a struct that can be easily deserialized inside Solidity.
struct PublicInputs {
    // merkle commitment to all authorities
    bytes32 authorities_root;
    // size of the authority set
    uint256 authorities_len;
    // BEEFY mmr leaf hash
    bytes32 leaf_hash;
    // Parachain header hashes
    bytes32[] headers;
}

struct Payload {
    bytes2 id;
    bytes data;
}

struct Commitment {
    Payload[] payload;
    uint256 blockNumber;
    uint256 validatorSetId;
}

struct AuthoritySetCommitment {
    /// Id of the set.
    uint256 id;
    /// Number of validators in the set.
    uint256 len;
    /// Merkle Root Hash built from BEEFY AuthorityIds.
    bytes32 root;
}

struct BeefyMmrLeaf {
    uint256 version;
    uint256 parentNumber;
    bytes32 parentHash;
    AuthoritySetCommitment nextAuthoritySet;
    bytes32 extra;
    uint256 kIndex;
    uint256 leafIndex;
}

struct BeefyConsensusState {
    /// block number for the latest mmr_root_hash
    uint256 latestHeight;
    /// Block number that the beefy protocol was activated on the relay chain.
    /// This should be the first block in the merkle-mountain-range tree.
    uint256 beefyActivationBlock;
    /// authorities for the current round
    AuthoritySetCommitment currentAuthoritySet;
    /// authorities for the next round
    AuthoritySetCommitment nextAuthoritySet;
}

struct PartialBeefyMmrLeaf {
    uint256 version;
    uint256 parentNumber;
    bytes32 parentHash;
    AuthoritySetCommitment nextAuthoritySet;
    bytes32 extra;
}

struct Parachain {
    /// k-index for latestHeadsRoot
    uint256 index;
    /// Parachain Id
    uint256 id;
    /// SCALE encoded header
    bytes header;
}

struct ParachainProof {
    Parachain parachain;
    Node[][] proof;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.20;

import {Bytes, ByteSlice} from "../Bytes.sol";

library ScaleCodec {
    // Decodes a SCALE encoded uint256 by converting bytes (bid endian) to little endian format
    function decodeUint256(bytes memory data) internal pure returns (uint256) {
        uint256 number;
        for (uint256 i = data.length; i > 0; i--) {
            number =
                number +
                uint256(uint8(data[i - 1])) *
                (2 ** (8 * (i - 1)));
        }
        return number;
    }

    // Decodes a SCALE encoded compact unsigned integer
    function decodeUintCompact(
        ByteSlice memory data
    ) internal pure returns (uint256 v) {
        uint8 b = Bytes.readByte(data); // read the first byte
        uint8 mode = b % 4; // bitwise operation

        uint256 value;
        if (mode == 0) {
            // [0, 63]
            value = b >> 2; // right shift to remove mode bits
        } else if (mode == 1) {
            // [64, 16383]
            uint8 bb = Bytes.readByte(data); // read the second byte
            uint64 r = bb; // convert to uint64
            r <<= 6; // multiply by * 2^6
            r += b >> 2; // right shift to remove mode bits
            value = r;
        } else if (mode == 2) {
            // [16384, 1073741823]
            uint8 b2 = Bytes.readByte(data); // read the next 3 bytes
            uint8 b3 = Bytes.readByte(data);
            uint8 b4 = Bytes.readByte(data);

            uint32 x1 = uint32(b) | (uint32(b2) << 8); // convert to little endian
            uint32 x2 = x1 | (uint32(b3) << 16);
            uint32 x3 = x2 | (uint32(b4) << 24);

            x3 >>= 2; // remove the last 2 mode bits
            value = uint256(x3);
        } else if (mode == 3) {
            // [1073741824, 4503599627370496]
            uint8 l = (b >> 2) + 4; // remove mode bits
            require(l <= 8, "unexpected prefix decoding Compact<Uint>");
            return decodeUint256(Bytes.read(data, l));
        } else {
            revert("Code should be unreachable");
        }
        return value;
    }

    // Decodes a SCALE encoded compact unsigned integer
    function decodeUintCompact(
        bytes memory data
    ) internal pure returns (uint256 v, uint8 m) {
        uint8 b = readByteAtIndex(data, 0); // read the first byte
        uint8 mode = b & 3; // bitwise operation

        uint256 value;
        if (mode == 0) {
            // [0, 63]
            value = b >> 2; // right shift to remove mode bits
        } else if (mode == 1) {
            // [64, 16383]
            uint8 bb = readByteAtIndex(data, 1); // read the second byte
            uint64 r = bb; // convert to uint64
            r <<= 6; // multiply by * 2^6
            r += b >> 2; // right shift to remove mode bits
            value = r;
        } else if (mode == 2) {
            // [16384, 1073741823]
            uint8 b2 = readByteAtIndex(data, 1); // read the next 3 bytes
            uint8 b3 = readByteAtIndex(data, 2);
            uint8 b4 = readByteAtIndex(data, 3);

            uint32 x1 = uint32(b) | (uint32(b2) << 8); // convert to little endian
            uint32 x2 = x1 | (uint32(b3) << 16);
            uint32 x3 = x2 | (uint32(b4) << 24);

            x3 >>= 2; // remove the last 2 mode bits
            value = uint256(x3);
        } else if (mode == 3) {
            // [1073741824, 4503599627370496]
            uint8 l = b >> 2; // remove mode bits
            require(
                l > 32,
                "Not supported: number cannot be greater than 32 bytes"
            );
        } else {
            revert("Code should be unreachable");
        }
        return (value, mode);
    }

    // The biggest compact supported uint is 2 ** 536 - 1.
    // But the biggest value supported by this method is 2 ** 256 - 1(max of uint256)
    function encodeUintCompact(uint256 v) internal pure returns (bytes memory) {
        if (v < 64) {
            return abi.encodePacked(uint8(v << 2));
        } else if (v < 2 ** 14) {
            return abi.encodePacked(reverse16(uint16(((v << 2) + 1))));
        } else if (v < 2 ** 30) {
            return abi.encodePacked(reverse32(uint32(((v << 2) + 2))));
        } else {
            bytes memory valueBytes = Bytes.removeEndingZero(
                abi.encodePacked(reverse256(v))
            );

            uint256 length = valueBytes.length;
            uint8 prefix = uint8(((length - 4) << 2) + 3);

            return abi.encodePacked(prefix, valueBytes);
        }
    }

    // Read a byte at a specific index and return it as type uint8
    function readByteAtIndex(
        bytes memory data,
        uint8 index
    ) internal pure returns (uint8) {
        return uint8(data[index]);
    }

    // Sources:
    //   * https://ethereum.stackexchange.com/questions/15350/how-to-convert-an-bytes-to-address-in-solidity/50528
    //   * https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel

    function reverse256(uint256 input) internal pure returns (uint256 v) {
        v = input;

        // swap bytes
        v =
            ((v &
                0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >>
                8) |
            ((v &
                0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) <<
                8);

        // swap 2-byte long pairs
        v =
            ((v &
                0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >>
                16) |
            ((v &
                0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) <<
                16);

        // swap 4-byte long pairs
        v =
            ((v &
                0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >>
                32) |
            ((v &
                0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) <<
                32);

        // swap 8-byte long pairs
        v =
            ((v &
                0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >>
                64) |
            ((v &
                0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) <<
                64);

        // swap 16-byte long pairs
        v = (v >> 128) | (v << 128);
    }

    function reverse128(uint128 input) internal pure returns (uint128 v) {
        v = input;

        // swap bytes
        v =
            ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00) >> 8) |
            ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF) << 8);

        // swap 2-byte long pairs
        v =
            ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000) >> 16) |
            ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF) << 16);

        // swap 4-byte long pairs
        v =
            ((v & 0xFFFFFFFF00000000FFFFFFFF00000000) >> 32) |
            ((v & 0x00000000FFFFFFFF00000000FFFFFFFF) << 32);

        // swap 8-byte long pairs
        v = (v >> 64) | (v << 64);
    }

    function reverse64(uint64 input) internal pure returns (uint64 v) {
        v = input;

        // swap bytes
        v = ((v & 0xFF00FF00FF00FF00) >> 8) | ((v & 0x00FF00FF00FF00FF) << 8);

        // swap 2-byte long pairs
        v = ((v & 0xFFFF0000FFFF0000) >> 16) | ((v & 0x0000FFFF0000FFFF) << 16);

        // swap 4-byte long pairs
        v = (v >> 32) | (v << 32);
    }

    function reverse32(uint32 input) internal pure returns (uint32 v) {
        v = input;

        // swap bytes
        v = ((v & 0xFF00FF00) >> 8) | ((v & 0x00FF00FF) << 8);

        // swap 2-byte long pairs
        v = (v >> 16) | (v << 16);
    }

    function reverse16(uint16 input) internal pure returns (uint16 v) {
        v = input;

        // swap bytes
        v = (v >> 8) | (v << 8);
    }

    function encode256(uint256 input) internal pure returns (bytes32) {
        return bytes32(reverse256(input));
    }

    function encode128(uint128 input) internal pure returns (bytes16) {
        return bytes16(reverse128(input));
    }

    function encode64(uint64 input) internal pure returns (bytes8) {
        return bytes8(reverse64(input));
    }

    function encode32(uint32 input) internal pure returns (bytes4) {
        return bytes4(reverse32(input));
    }

    function encode16(uint16 input) internal pure returns (bytes2) {
        return bytes2(reverse16(input));
    }

    function encodeBytes(
        bytes memory input
    ) internal pure returns (bytes memory) {
        return abi.encodePacked(encodeUintCompact(input.length), input);
    }
}

// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.20;

import {Memory} from "./Memory.sol";

struct ByteSlice {
    bytes data;
    uint256 offset;
}

library Bytes {
    uint256 internal constant BYTES_HEADER_SIZE = 32;

    // Checks if two `bytes memory` variables are equal. This is done using hashing,
    // which is much more gas efficient then comparing each byte individually.
    // Equality means that:
    //  - 'self.length == other.length'
    //  - For 'n' in '[0, self.length)', 'self[n] == other[n]'
    function equals(
        bytes memory self,
        bytes memory other
    ) internal pure returns (bool equal) {
        if (self.length != other.length) {
            return false;
        }
        uint256 addr;
        uint256 addr2;
        assembly {
            addr := add(self, /*BYTES_HEADER_SIZE*/ 32)
            addr2 := add(other, /*BYTES_HEADER_SIZE*/ 32)
        }
        equal = Memory.equals(addr, addr2, self.length);
    }

    function readByte(ByteSlice memory self) internal pure returns (uint8) {
        if (self.offset + 1 > self.data.length) {
            revert("Out of range");
        }

        uint8 b = uint8(self.data[self.offset]);
        self.offset += 1;

        return b;
    }

    // Copies 'len' bytes from 'self' into a new array, starting at the provided 'startIndex'.
    // Returns the new copy.
    // Requires that:
    //  - 'startIndex + len <= self.length'
    // The length of the substring is: 'len'
    function read(
        ByteSlice memory self,
        uint256 len
    ) internal pure returns (bytes memory) {
        require(self.offset + len <= self.data.length);
        if (len == 0) {
            return "";
        }
        uint256 addr = Memory.dataPtr(self.data);
        bytes memory slice = Memory.toBytes(addr + self.offset, len);
        self.offset += len;
        return slice;
    }

    // Copies a section of 'self' into a new array, starting at the provided 'startIndex'.
    // Returns the new copy.
    // Requires that 'startIndex <= self.length'
    // The length of the substring is: 'self.length - startIndex'
    function substr(
        bytes memory self,
        uint256 startIndex
    ) internal pure returns (bytes memory) {
        require(startIndex <= self.length);
        uint256 len = self.length - startIndex;
        uint256 addr = Memory.dataPtr(self);
        return Memory.toBytes(addr + startIndex, len);
    }

    // Copies 'len' bytes from 'self' into a new array, starting at the provided 'startIndex'.
    // Returns the new copy.
    // Requires that:
    //  - 'startIndex + len <= self.length'
    // The length of the substring is: 'len'
    function substr(
        bytes memory self,
        uint256 startIndex,
        uint256 len
    ) internal pure returns (bytes memory) {
        require(startIndex + len <= self.length);
        if (len == 0) {
            return "";
        }
        uint256 addr = Memory.dataPtr(self);
        return Memory.toBytes(addr + startIndex, len);
    }

    // Combines 'self' and 'other' into a single array.
    // Returns the concatenated arrays:
    //  [self[0], self[1], ... , self[self.length - 1], other[0], other[1], ... , other[other.length - 1]]
    // The length of the new array is 'self.length + other.length'
    function concat(
        bytes memory self,
        bytes memory other
    ) internal pure returns (bytes memory) {
        bytes memory ret = new bytes(self.length + other.length);
        uint256 src;
        uint256 srcLen;
        (src, srcLen) = Memory.fromBytes(self);
        uint256 src2;
        uint256 src2Len;
        (src2, src2Len) = Memory.fromBytes(other);
        uint256 dest;
        (dest, ) = Memory.fromBytes(ret);
        uint256 dest2 = dest + srcLen;
        Memory.copy(src, dest, srcLen);
        Memory.copy(src2, dest2, src2Len);
        return ret;
    }

    function toBytes32(bytes memory self) internal pure returns (bytes32 out) {
        require(self.length >= 32, "Bytes:: toBytes32: data is to short.");
        assembly {
            out := mload(add(self, 32))
        }
    }

    function toBytes16(
        bytes memory self,
        uint256 offset
    ) internal pure returns (bytes16 out) {
        for (uint256 i = 0; i < 16; i++) {
            out |= bytes16(bytes1(self[offset + i]) & 0xFF) >> (i * 8);
        }
    }

    function toBytes8(
        bytes memory self,
        uint256 offset
    ) internal pure returns (bytes8 out) {
        for (uint256 i = 0; i < 8; i++) {
            out |= bytes8(bytes1(self[offset + i]) & 0xFF) >> (i * 8);
        }
    }

    function toBytes4(
        bytes memory self,
        uint256 offset
    ) internal pure returns (bytes4) {
        bytes4 out;

        for (uint256 i = 0; i < 4; i++) {
            out |= bytes4(self[offset + i] & 0xFF) >> (i * 8);
        }
        return out;
    }

    function toBytes2(
        bytes memory self,
        uint256 offset
    ) internal pure returns (bytes2) {
        bytes2 out;

        for (uint256 i = 0; i < 2; i++) {
            out |= bytes2(self[offset + i] & 0xFF) >> (i * 8);
        }
        return out;
    }

    function removeLeadingZero(
        bytes memory data
    ) internal pure returns (bytes memory) {
        uint256 length = data.length;

        uint256 startIndex = 0;
        for (uint256 i = 0; i < length; i++) {
            if (data[i] != 0) {
                startIndex = i;
                break;
            }
        }

        return substr(data, startIndex);
    }

    function removeEndingZero(
        bytes memory data
    ) internal pure returns (bytes memory) {
        uint256 length = data.length;

        uint256 endIndex = 0;
        for (uint256 i = length - 1; i >= 0; i--) {
            if (data[i] != 0) {
                endIndex = i;
                break;
            }
        }

        return substr(data, 0, endIndex + 1);
    }

    function reverse(
        bytes memory inbytes
    ) internal pure returns (bytes memory) {
        uint256 inlength = inbytes.length;
        bytes memory outbytes = new bytes(inlength);

        for (uint256 i = 0; i <= inlength - 1; i++) {
            outbytes[i] = inbytes[inlength - i - 1];
        }

        return outbytes;
    }
}

// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.17;

import {StateCommitment} from "@hyperbridge/core/interfaces/IConsensus.sol";
import "@polytope-labs/solidity-merkle-trees/src/trie/Bytes.sol";
import "@polytope-labs/solidity-merkle-trees/src/trie/substrate/ScaleCodec.sol";

struct DigestItem {
    bytes4 consensusId;
    bytes data;
}

struct Digest {
    bool isPreRuntime;
    DigestItem preruntime;
    bool isConsensus;
    DigestItem consensus;
    bool isSeal;
    DigestItem seal;
    bool isOther;
    bytes other;
    bool isRuntimeEnvironmentUpdated;
}

struct Header {
    bytes32 parentHash;
    uint256 number;
    bytes32 stateRoot;
    bytes32 extrinsicRoot;
    Digest[] digests;
}

library HeaderImpl {
    /// Digest Item ID
    bytes4 public constant ISMP_CONSENSUS_ID = bytes4("ISMP");
    /// ConsensusID for aura
    bytes4 public constant AURA_CONSENSUS_ID = bytes4("aura");
    /// Slot duration in milliseconds
    uint256 public constant SLOT_DURATION = 12000;

    error TimestampNotFound();
    error ChildTrieRootNotFound();

    // Extracts the `StateCommitment` from the provided header.
    function stateCommitment(Header calldata self) public pure returns (StateCommitment memory) {
        bytes32 mmrRoot;
        bytes32 childTrieRoot;
        uint256 timestamp;

        for (uint256 j = 0; j < self.digests.length; j++) {
            if (self.digests[j].isConsensus && self.digests[j].consensus.consensusId == ISMP_CONSENSUS_ID) {
                mmrRoot = Bytes.toBytes32(self.digests[j].consensus.data[:32]);
                childTrieRoot = Bytes.toBytes32(self.digests[j].consensus.data[32:]);
            }

            if (self.digests[j].isPreRuntime && self.digests[j].preruntime.consensusId == AURA_CONSENSUS_ID) {
                uint256 slot = ScaleCodec.decodeUint256(self.digests[j].preruntime.data);
                timestamp = slot * SLOT_DURATION;
            }
        }

        // sanity check
        if (timestamp == 0) revert TimestampNotFound();
        if (childTrieRoot == bytes32(0)) revert ChildTrieRootNotFound();

        return StateCommitment({timestamp: timestamp, overlayRoot: mmrRoot, stateRoot: childTrieRoot});
    }
}

File 11 of 12 : Types.sol
// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.20;

// Outcome of a successfully verified merkle-patricia proof
struct StorageValue {
    // the storage key
    bytes key;
    // the encoded value
    bytes value;
}

/// @title A representation of a Merkle tree node
struct Node {
    // Distance of the node to the leftmost node
    uint256 k_index;
    // A hash of the node itself
    bytes32 node;
}

/// @title A representation of a MerkleMountainRange leaf
struct MmrLeaf {
    // the leftmost index of a node
    uint256 k_index;
    // The position in the tree
    uint256 leaf_index;
    // The hash of the position in the tree
    bytes32 hash;
}

struct Iterator {
    uint256 offset;
    bytes32[] data;
}

// Copyright (C) Polytope Labs Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pragma solidity ^0.8.20;

library Memory {
    uint256 internal constant WORD_SIZE = 32;

    // Compares the 'len' bytes starting at address 'addr' in memory with the 'len'
    // bytes starting at 'addr2'.
    // Returns 'true' if the bytes are the same, otherwise 'false'.
    function equals(
        uint256 addr,
        uint256 addr2,
        uint256 len
    ) internal pure returns (bool equal) {
        assembly {
            equal := eq(keccak256(addr, len), keccak256(addr2, len))
        }
    }

    // Compares the 'len' bytes starting at address 'addr' in memory with the bytes stored in
    // 'bts'. It is allowed to set 'len' to a lower value then 'bts.length', in which case only
    // the first 'len' bytes will be compared.
    // Requires that 'bts.length >= len'

    function equals(
        uint256 addr,
        uint256 len,
        bytes memory bts
    ) internal pure returns (bool equal) {
        require(bts.length >= len);
        uint256 addr2;
        assembly {
            addr2 := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
        return equals(addr, addr2, len);
    }
    // Returns a memory pointer to the data portion of the provided bytes array.

    function dataPtr(bytes memory bts) internal pure returns (uint256 addr) {
        assembly {
            addr := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
    }

    // Creates a 'bytes memory' variable from the memory address 'addr', with the
    // length 'len'. The function will allocate new memory for the bytes array, and
    // the 'len bytes starting at 'addr' will be copied into that new memory.
    function toBytes(
        uint256 addr,
        uint256 len
    ) internal pure returns (bytes memory bts) {
        bts = new bytes(len);
        uint256 btsptr;
        assembly {
            btsptr := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
        copy(addr, btsptr, len);
    }

    // Copies 'self' into a new 'bytes memory'.
    // Returns the newly created 'bytes memory'
    // The returned bytes will be of length '32'.
    function toBytes(bytes32 self) internal pure returns (bytes memory bts) {
        bts = new bytes(32);
        assembly {
            mstore(add(bts, /*BYTES_HEADER_SIZE*/ 32), self)
        }
    }

    // Copy 'len' bytes from memory address 'src', to address 'dest'.
    // This function does not check the or destination, it only copies
    // the bytes.
    function copy(uint256 src, uint256 dest, uint256 len) internal pure {
        // Copy word-length chunks while possible
        for (; len >= WORD_SIZE; len -= WORD_SIZE) {
            assembly {
                mstore(dest, mload(src))
            }
            dest += WORD_SIZE;
            src += WORD_SIZE;
        }

        // Copy remaining bytes
        uint256 mask = len == 0
            ? 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
            : 256 ** (WORD_SIZE - len) - 1;
        assembly {
            let srcpart := and(mload(src), not(mask))
            let destpart := and(mload(dest), mask)
            mstore(dest, or(destpart, srcpart))
        }
    }

    // This function does the same as 'dataPtr(bytes memory)', but will also return the
    // length of the provided bytes array.
    function fromBytes(
        bytes memory bts
    ) internal pure returns (uint256 addr, uint256 len) {
        len = bts.length;
        assembly {
            addr := add(bts, /*BYTES_HEADER_SIZE*/ 32)
        }
    }
}

Settings
{
  "remappings": [
    "@hyperbridge/core/=node_modules/@hyperbridge/core/contracts/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@polytope-labs/=node_modules/@polytope-labs/",
    "@uniswap/=node_modules/@uniswap/",
    "stringutils/=lib/solidity-stringutils/src/",
    "@sp1-contracts/=lib/sp1-contracts/contracts/src/",
    "ds-test/=lib/solidity-stringutils/lib/ds-test/src/",
    "erc4626-tests/=lib/sp1-contracts/contracts/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/sp1-contracts/contracts/lib/openzeppelin-contracts/",
    "solidity-stringutils/=lib/solidity-stringutils/",
    "sp1-contracts/=lib/sp1-contracts/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {
    "src/consensus/SP1Beefy.sol": {
      "HeaderImpl": "0x2cb960d03080a42ac4d9d53c0cc87cd6795ec9b3"
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract ISP1Verifier","name":"verifier","type":"address"},{"internalType":"bytes32","name":"verificationKey","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"IllegalGenesisBlock","type":"error"},{"inputs":[],"name":"StaleHeight","type":"error"},{"inputs":[],"name":"UnknownAuthoritySet","type":"error"},{"inputs":[],"name":"_verificationKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_verifier","outputs":[{"internalType":"contract ISP1Verifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"validatorSetId","type":"uint256"}],"internalType":"struct MiniCommitment","name":"commitment","type":"tuple"},{"components":[{"internalType":"uint256","name":"version","type":"uint256"},{"internalType":"uint256","name":"parentNumber","type":"uint256"},{"internalType":"bytes32","name":"parentHash","type":"bytes32"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"len","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"internalType":"struct AuthoritySetCommitment","name":"nextAuthoritySet","type":"tuple"},{"internalType":"bytes32","name":"extra","type":"bytes32"}],"internalType":"struct PartialBeefyMmrLeaf","name":"mmrLeaf","type":"tuple"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"header","type":"bytes"}],"internalType":"struct ParachainHeader[]","name":"headers","type":"tuple[]"},{"internalType":"bytes","name":"proof","type":"bytes"}],"internalType":"struct SP1BeefyProof","name":"s","type":"tuple"},{"components":[{"internalType":"bytes32","name":"authorities_root","type":"bytes32"},{"internalType":"uint256","name":"authorities_len","type":"uint256"},{"internalType":"bytes32","name":"leaf_hash","type":"bytes32"},{"internalType":"bytes32[]","name":"headers","type":"bytes32[]"}],"internalType":"struct PublicInputs","name":"p","type":"tuple"}],"name":"noOp","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedState","type":"bytes"},{"internalType":"bytes","name":"encodedProof","type":"bytes"}],"name":"verifyConsensus","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"components":[{"internalType":"uint256","name":"stateMachineId","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"},{"components":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"bytes32","name":"overlayRoot","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"}],"internalType":"struct StateCommitment","name":"commitment","type":"tuple"}],"internalType":"struct IntermediateState[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"}]

60c03461008a57601f611ab738819003918201601f19168301916001600160401b0383118484101761008e57808492604094855283398101031261008a578051906001600160a01b038216820361008a57602001519060a052608052604051611a1490816100a382396080518181816105180152610c39015260a0518181816107210152610bf30152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a71461006457806309a07dd31461005f5780631a2bd4871461005a5780637d7555981461005557638a17265114610050575f80fd5b61070c565b610604565b610501565b610425565b346100b85760203660031901126100b85760043563ffffffff60e01b81168091036100b857630faeaab360e31b81149081156100a7575b50151560805260206080f35b6301ffc9a760e01b1490508161009b565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176100eb57604052565b6100bc565b606081019081106001600160401b038211176100eb57604052565b60a081019081106001600160401b038211176100eb57604052565b608081019081106001600160401b038211176100eb57604052565b90601f801991011681019081106001600160401b038211176100eb57604052565b60405190610171608083610141565b565b60405190610171606083610141565b60405190610171604083610141565b6040519061017160a083610141565b91908260409103126100b8576040516101b8816100d0565b6020808294803584520135910152565b91908260609103126100b8576040516101e0816100f0565b604080829480358452602081013560208501520135910152565b91909160e0818403126100b857608060c0604051926102188461010b565b61023e8496823586526020830135602087015260408301356040870152606083016101c8565b60608501520135910152565b6001600160401b0381116100eb5760051b60200190565b6001600160401b0381116100eb57601f01601f191660200190565b81601f820112156100b85780359061029382610261565b926102a16040519485610141565b828452602083830101116100b857815f926020809301838601378301015290565b9080601f830112156100b8578135916102da8361024a565b926102e86040519485610141565b80845260208085019160051b830101918383116100b85760208101915b83831061031457505050505090565b82356001600160401b0381116100b8578201906040828703601f1901126100b85760405190610342826100d0565b602083013582526040830135916001600160401b0383116100b85761036f8860208096958196010161027c565b83820152815201920191610305565b91906080838203126100b85760405161039681610126565b80938035825260208101356020830152604081013560408301526060810135906001600160401b0382116100b857019180601f840112156100b85782356103dc8161024a565b936103ea6040519586610141565b81855260208086019260051b8201019283116100b857602001905b8282106104155750505060600152565b8135815260209182019101610405565b346100b85760403660031901126100b8576004356001600160401b0381116100b85761016060031982360301126100b8576040519061046382610126565b61047036826004016101a0565b825261047f36604483016101fa565b60208301526101248101356001600160401b0381116100b8576104a890600436918401016102c2565b60408301526101448101356001600160401b0381116100b85760609160046104d3923692010161027c565b9101526024356001600160401b0381116100b8576104f590369060040161037e565b005b5f9103126100b857565b346100b8575f3660031901126100b85760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b9181601f840112156100b8578235916001600160401b0383116100b857602083818601950101116100b857565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9061059f90604083526040830190610568565b906020818303910152602080835192838152019201905f5b8181106105c45750505090565b909192602060a0600192604080885180518452858101518685015201518051828401528481015160608401520151608082015201940191019190916105b7565b346100b85760403660031901126100b8576004356001600160401b0381116100b85761063490369060040161053b565b6024356001600160401b0381116100b85761065390369060040161053b565b9091830192610100818503126100b8576106b76106eb936106da936106aa6106f99760a06040519661068488610126565b803588526020810135602089015261069f83604083016101c8565b6040890152016101c8565b6060850152810190610750565b916106c3949394610162565b948552602085015260408401526060830152610b3f565b9290604051928391602083016107b7565b03601f198101835282610141565b6107086040519283928361058c565b0390f35b346100b8575f3660031901126100b8576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b90610160828203126100b85761076681836101a0565b9261077482604085016101fa565b926101208101356001600160401b0381116100b857836107959183016102c2565b926101408201356001600160401b0381116100b8576107b4920161027c565b90565b6101719092919260a0606061010083019580518452602081015160208501526107fc604082015160408601906040809180518452602081015160208501520151910152565b01519101906040809180518452602081015160208501520151910152565b60405190610827826100f0565b5f6040838281528260208201520152565b6040519061084582610126565b815f81525f602082015261085761081a565b6040820152606061086661081a565b910152565b906108758261024a565b6108826040519182610141565b8281528092610893601f199161024a565b0190602036910137565b634e487b7160e01b5f52603260045260245ffd5b80518210156108c55760209160051b010190565b61089d565b9060208252602060c0606060a08501938051848701528381015160408701526040810151828701520151936080808201528451809452019201905f5b8181106109135750505090565b8251845260209384019390920191600101610906565b91610946906107b494928452606060208501526060840190610568565b916040818403910152610568565b6040513d5f823e3d90fd5b906109698261024a565b6109766040519182610141565b8281528092610987601f199161024a565b01905f5b82811061099757505050565b6020906040516109a6816100f0565b5f81525f838201526109b661081a565b60408201528282850101520161098b565b908160609103126100b85760408051916109e0836100f0565b80518352602081015160208401520151604082015290565b90604060206107b49363ffffffff60e01b81511684520151918160208201520190610568565b60208152608060c082019280516020840152602081015160408401526040810151606084015260608101518284015201519160a080830152825180915260e0820191602060e08360051b8301019401925f915b838310610a8057505050505090565b909192939460208060019260df19858203018652610b30895191610aa681845115159052565b61010080610b26610b08610aea610acc898901516101208b8901526101208801906109f8565b604089810151151590880152606089015187820360608901526109f8565b60808881015115159087015260a088015186820360a08801526109f8565b60c08781015115159086015260e087015185820360e0870152610568565b9401511515910152565b97019301930191939290610a71565b919091610b4a610838565b508251815181511115610e1357610b5f61081a565b506020810151606083019081515181145f14610def575080515b6040860195865151610b8a8161086b565b905f5b818110610dc4575050610be86106eb9160406020860151950151906020850195610bb78751610f16565b6020815191012090610bc7610162565b938452602084015260408301526060820152604051928391602083016108ca565b606060018060a01b037f000000000000000000000000000000000000000000000000000000000000000016920151823b156100b85760405163020a49e360e51b8152925f92849283918291610c61917f000000000000000000000000000000000000000000000000000000000000000060048501610929565b03915afa8015610d9657610daa575b5085515195610c7e8761095f565b96732cb960d03080a42ac4d9d53c0cc87cd6795ec9b3915f5b828110610cd457505050506060815101515190825191825110610cbf575b5050505181529190565b606091604086015251015190525f8080610cb5565b610cdf8183516108b1565b5190610cee6020830151611196565b916020830190815115610d9b576060610d1b9460405180968192638b3e82b560e01b835260048301610a1e565b03818a5af4908115610d96576001945f92610d66575b50519151610d3d610173565b92835260208301526040820152610d54828d6108b1565b52610d5f818c6108b1565b5001610c97565b610d8891925060603d8111610d8f575b610d808183610141565b8101906109c7565b905f610d31565b503d610d76565b610954565b63b4eb9e5160e01b5f5260045ffd5b80610db85f610dbe93610141565b806104f7565b5f610c70565b806020610dd46001938d516108b1565b51015160208151910120610de882866108b1565b5201610b8d565b6040840190815151145f14610e045751610b79565b637202e68560e11b5f5260045ffd5b63beda4fc360e01b5f5260045ffd5b805191908290602001825e015f815290565b600461017191610e4f94936040519586926020840190610e22565b9063ffffffff60e01b16815203601b19810185520183610141565b9060405191602083015260208252610171604083610141565b600861017191610e9e94936040519586926020840190610e22565b906001600160401b0360c01b16815203601719810185520183610141565b6040516001600160e01b031990911660208201529190610171908390610ee6906024830190610e22565b03601f198101845283610141565b61017190610ee6610f1094936040519586936020850190610e22565b90610e22565b6107b490611094610f9882516040519060ff60f81b9060f81b16602082015260018152610f44602182610141565b610f92610f58602086015163ffffffff1690565b63ff00ff00600882811b9190911691901c62ff00ff1617601081811b63ffff00001691901c61ffff161760e01b6001600160e01b03191690565b90610e34565b611094608061108c610fad6040870151610e6a565b61108661105d6060890192611057610fcd8551516001600160401b031690565b67ffffffffffff000067ff00ff00ff00ff0066ff00ff00ff00ff8360081c169260081b169165ffff0000ffff65ffff0000ff0065ffffffffffff67ffff0000ffff0000861666ff0000ffff000085161760101c16941691161760101b161767ffffffff0000000063ffffffff8260201c169160201b166001600160401b0360c01b911760c01b1690565b90610e83565b91516110806040611078610f58602085015163ffffffff1690565b920151610e6a565b90610ebc565b94610ef4565b940151610e6a565b90610ef4565b604051906110a78261010b565b60606080835f81525f60208201525f60408201525f838201520152565b604051906110d1826100d0565b60606020835f81520152565b6040519061012082018281106001600160401b038211176100eb576040525f6101008382815261110b6110c4565b602082015282604082015261111e6110c4565b60608201528260808201526111316110c4565b60a08201528260c0820152606060e08201520152565b906111518261024a565b61115e6040519182610141565b828152809261116f601f199161024a565b01905f5b82811061117f57505050565b60209061118a6110dd565b82828501015201611173565b61119e61109a565b506111a7610182565b9081525f60208201526111c16111bc82611308565b6114db565b906111cb816115cb565b6111d76111bc83611308565b6111e36111bc84611308565b916111ed846115cb565b6111f681611147565b945f5b8281106112255750505061120b610191565b948552602085015260408401526060830152608082015290565b60019061123183611755565b60ff61123b6110dd565b9116806112675750600160c08201525b611255828a6108b1565b5261126081896108b1565b50016111f9565b6004810361128b575060016040820152611280846117d2565b60608201525b61124b565b600581036112ae5750600160808201526112a4846117d2565b60a082015261124b565b600681036112ce5750600181526112c4846117d2565b602082015261124b565b60080361128657600161010082015261124b565b634e487b7160e01b5f52601160045260245ffd5b9190820180921161130357565b6112e2565b6020810180516020810180911161130357825151106100b8576020915182825182010192839101116113035761133e6020610261565b9161134c6040519384610141565b6020835261135a6020610261565b6020840190601f19013682379060205b60208110156113b9578061139a57505f19905b811990511690825116179052611395602082516112f6565b905290565b6113ae6113a96113b39261193c565b6119cf565b61194a565b9061137d565b909182518152602081018091116113035791602081018091116113035790601f1981019081111561136a576112e2565b919060208301805182810180911161130357845151106100b85781156114c3576020935184825182010194859101116113035761142582610261565b916114336040519384610141565b80835261143f81610261565b602084019590601f19013687378195905b6020871015611494576113959394959680155f1461147f57505f19905b518251821691191617905282516112f6565b6113ae6113a961148e9261193c565b9061146d565b9081518152602081018091116113035790602081018091116113035795601f1981019081116113035795611450565b505090506040516114d5602082610141565b5f815290565b60208151106114eb576020015190565b60405162461bcd60e51b8152602060048201526024808201527f42797465733a3a20746f427974657333323a206461746120697320746f20736860448201526337b93a1760e11b6064820152608490fd5b60ff60049116019060ff821161130357565b1561155557565b60405162461bcd60e51b815260206004820152602860248201527f756e657870656374656420707265666978206465636f64696e6720436f6d706160448201526731ba1e2ab4b73a1f60c11b6064820152608490fd5b906001600160401b03809116911601906001600160401b03821161130357565b6115d481611755565b60038116806115f057506107b4915060021c603f165b60ff1690565b6001810361164157506116359061162f6115ea6116256116156115ea6107b497611755565b60061b67ffffffffffffffc01690565b9260021c603f1690565b906115ab565b6001600160401b031690565b600281036116c057506116b7906116aa60ff8461169b826116646107b498611755565b958161168a8161167c61167688611755565b97611755565b991660081b63ffffff001690565b911617921660101b63ffff00001690565b17921660181b63ff0000001690565b1760021c633fffffff1690565b63ffffffff1690565b6003036116ff576107b49160ff6116e66116e16116fa94603f9060021c1690565b61153c565b16906116f5600883111561154e565b6113e9565b611958565b60405162461bcd60e51b815260206004820152601a60248201527f436f64652073686f756c6420626520756e726561636861626c650000000000006044820152606490fd5b9081518110156108c5570160200190565b6020810190815160018101809111611303578151511061179e575181516001600160f81b0319916117869190611744565b511660f81c9080519060018201809211611303575290565b60405162461bcd60e51b815260206004820152600c60248201526b4f7574206f662072616e676560a01b6044820152606490fd5b6117da6110c4565b50602081019081516004810180911161130357815151106100b85760209181518382518201019384910111611303576118136004610261565b926118216040519485610141565b6004845261182f6004610261565b6020850190601f19013682379060045b602081101561190c57806118f757505f19905b81199051169082511617905261186a600482516112f6565b90525f915f905b600482106118b15750508061188861188e926115cb565b906113e9565b6118a9611899610182565b6001600160e01b03199093168352565b602082015290565b90926001600160f81b03196118c68584611744565b5116908460031b9185830460081486151715611303576001926001600160e01b0319918216901c1617930190611871565b6113ae6113a96119069261193c565b90611852565b909182518152602081018091116113035791602081018091116113035790601f1981019081111561183f576112e2565b602003906020821161130357565b5f1981019190821161130357565b80515f91815b61196757505090565b90915f1983018381116113035761197e8184611744565b5160f81c90600381901b906001600160fd1b038116036113035760ff8111611303576001901b90818102918183041490151715611303576119be916112f6565b918015611303575f1901908161195e565b601f8111611303576101000a9056fea264697066735822122016aa4d8047b1ad8f3df8cf9c0bc211c3e8c46005ba9e6d745f3404819a766f5a64736f6c634300081e003300000000000000000000000065b299f6d365f34a04b67f602b89f6fab094a01200468fb8911ecec00d7fd724627ea49172c901dfe0af8749b0af7a90c33e1948

Deployed Bytecode

0x60806040526004361015610011575f80fd5b5f3560e01c806301ffc9a71461006457806309a07dd31461005f5780631a2bd4871461005a5780637d7555981461005557638a17265114610050575f80fd5b61070c565b610604565b610501565b610425565b346100b85760203660031901126100b85760043563ffffffff60e01b81168091036100b857630faeaab360e31b81149081156100a7575b50151560805260206080f35b6301ffc9a760e01b1490508161009b565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176100eb57604052565b6100bc565b606081019081106001600160401b038211176100eb57604052565b60a081019081106001600160401b038211176100eb57604052565b608081019081106001600160401b038211176100eb57604052565b90601f801991011681019081106001600160401b038211176100eb57604052565b60405190610171608083610141565b565b60405190610171606083610141565b60405190610171604083610141565b6040519061017160a083610141565b91908260409103126100b8576040516101b8816100d0565b6020808294803584520135910152565b91908260609103126100b8576040516101e0816100f0565b604080829480358452602081013560208501520135910152565b91909160e0818403126100b857608060c0604051926102188461010b565b61023e8496823586526020830135602087015260408301356040870152606083016101c8565b60608501520135910152565b6001600160401b0381116100eb5760051b60200190565b6001600160401b0381116100eb57601f01601f191660200190565b81601f820112156100b85780359061029382610261565b926102a16040519485610141565b828452602083830101116100b857815f926020809301838601378301015290565b9080601f830112156100b8578135916102da8361024a565b926102e86040519485610141565b80845260208085019160051b830101918383116100b85760208101915b83831061031457505050505090565b82356001600160401b0381116100b8578201906040828703601f1901126100b85760405190610342826100d0565b602083013582526040830135916001600160401b0383116100b85761036f8860208096958196010161027c565b83820152815201920191610305565b91906080838203126100b85760405161039681610126565b80938035825260208101356020830152604081013560408301526060810135906001600160401b0382116100b857019180601f840112156100b85782356103dc8161024a565b936103ea6040519586610141565b81855260208086019260051b8201019283116100b857602001905b8282106104155750505060600152565b8135815260209182019101610405565b346100b85760403660031901126100b8576004356001600160401b0381116100b85761016060031982360301126100b8576040519061046382610126565b61047036826004016101a0565b825261047f36604483016101fa565b60208301526101248101356001600160401b0381116100b8576104a890600436918401016102c2565b60408301526101448101356001600160401b0381116100b85760609160046104d3923692010161027c565b9101526024356001600160401b0381116100b8576104f590369060040161037e565b005b5f9103126100b857565b346100b8575f3660031901126100b85760206040517f00468fb8911ecec00d7fd724627ea49172c901dfe0af8749b0af7a90c33e19488152f35b9181601f840112156100b8578235916001600160401b0383116100b857602083818601950101116100b857565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9061059f90604083526040830190610568565b906020818303910152602080835192838152019201905f5b8181106105c45750505090565b909192602060a0600192604080885180518452858101518685015201518051828401528481015160608401520151608082015201940191019190916105b7565b346100b85760403660031901126100b8576004356001600160401b0381116100b85761063490369060040161053b565b6024356001600160401b0381116100b85761065390369060040161053b565b9091830192610100818503126100b8576106b76106eb936106da936106aa6106f99760a06040519661068488610126565b803588526020810135602089015261069f83604083016101c8565b6040890152016101c8565b6060850152810190610750565b916106c3949394610162565b948552602085015260408401526060830152610b3f565b9290604051928391602083016107b7565b03601f198101835282610141565b6107086040519283928361058c565b0390f35b346100b8575f3660031901126100b8576040517f00000000000000000000000065b299f6d365f34a04b67f602b89f6fab094a0126001600160a01b03168152602090f35b90610160828203126100b85761076681836101a0565b9261077482604085016101fa565b926101208101356001600160401b0381116100b857836107959183016102c2565b926101408201356001600160401b0381116100b8576107b4920161027c565b90565b6101719092919260a0606061010083019580518452602081015160208501526107fc604082015160408601906040809180518452602081015160208501520151910152565b01519101906040809180518452602081015160208501520151910152565b60405190610827826100f0565b5f6040838281528260208201520152565b6040519061084582610126565b815f81525f602082015261085761081a565b6040820152606061086661081a565b910152565b906108758261024a565b6108826040519182610141565b8281528092610893601f199161024a565b0190602036910137565b634e487b7160e01b5f52603260045260245ffd5b80518210156108c55760209160051b010190565b61089d565b9060208252602060c0606060a08501938051848701528381015160408701526040810151828701520151936080808201528451809452019201905f5b8181106109135750505090565b8251845260209384019390920191600101610906565b91610946906107b494928452606060208501526060840190610568565b916040818403910152610568565b6040513d5f823e3d90fd5b906109698261024a565b6109766040519182610141565b8281528092610987601f199161024a565b01905f5b82811061099757505050565b6020906040516109a6816100f0565b5f81525f838201526109b661081a565b60408201528282850101520161098b565b908160609103126100b85760408051916109e0836100f0565b80518352602081015160208401520151604082015290565b90604060206107b49363ffffffff60e01b81511684520151918160208201520190610568565b60208152608060c082019280516020840152602081015160408401526040810151606084015260608101518284015201519160a080830152825180915260e0820191602060e08360051b8301019401925f915b838310610a8057505050505090565b909192939460208060019260df19858203018652610b30895191610aa681845115159052565b61010080610b26610b08610aea610acc898901516101208b8901526101208801906109f8565b604089810151151590880152606089015187820360608901526109f8565b60808881015115159087015260a088015186820360a08801526109f8565b60c08781015115159086015260e087015185820360e0870152610568565b9401511515910152565b97019301930191939290610a71565b919091610b4a610838565b508251815181511115610e1357610b5f61081a565b506020810151606083019081515181145f14610def575080515b6040860195865151610b8a8161086b565b905f5b818110610dc4575050610be86106eb9160406020860151950151906020850195610bb78751610f16565b6020815191012090610bc7610162565b938452602084015260408301526060820152604051928391602083016108ca565b606060018060a01b037f00000000000000000000000065b299f6d365f34a04b67f602b89f6fab094a01216920151823b156100b85760405163020a49e360e51b8152925f92849283918291610c61917f00468fb8911ecec00d7fd724627ea49172c901dfe0af8749b0af7a90c33e194860048501610929565b03915afa8015610d9657610daa575b5085515195610c7e8761095f565b96732cb960d03080a42ac4d9d53c0cc87cd6795ec9b3915f5b828110610cd457505050506060815101515190825191825110610cbf575b5050505181529190565b606091604086015251015190525f8080610cb5565b610cdf8183516108b1565b5190610cee6020830151611196565b916020830190815115610d9b576060610d1b9460405180968192638b3e82b560e01b835260048301610a1e565b03818a5af4908115610d96576001945f92610d66575b50519151610d3d610173565b92835260208301526040820152610d54828d6108b1565b52610d5f818c6108b1565b5001610c97565b610d8891925060603d8111610d8f575b610d808183610141565b8101906109c7565b905f610d31565b503d610d76565b610954565b63b4eb9e5160e01b5f5260045ffd5b80610db85f610dbe93610141565b806104f7565b5f610c70565b806020610dd46001938d516108b1565b51015160208151910120610de882866108b1565b5201610b8d565b6040840190815151145f14610e045751610b79565b637202e68560e11b5f5260045ffd5b63beda4fc360e01b5f5260045ffd5b805191908290602001825e015f815290565b600461017191610e4f94936040519586926020840190610e22565b9063ffffffff60e01b16815203601b19810185520183610141565b9060405191602083015260208252610171604083610141565b600861017191610e9e94936040519586926020840190610e22565b906001600160401b0360c01b16815203601719810185520183610141565b6040516001600160e01b031990911660208201529190610171908390610ee6906024830190610e22565b03601f198101845283610141565b61017190610ee6610f1094936040519586936020850190610e22565b90610e22565b6107b490611094610f9882516040519060ff60f81b9060f81b16602082015260018152610f44602182610141565b610f92610f58602086015163ffffffff1690565b63ff00ff00600882811b9190911691901c62ff00ff1617601081811b63ffff00001691901c61ffff161760e01b6001600160e01b03191690565b90610e34565b611094608061108c610fad6040870151610e6a565b61108661105d6060890192611057610fcd8551516001600160401b031690565b67ffffffffffff000067ff00ff00ff00ff0066ff00ff00ff00ff8360081c169260081b169165ffff0000ffff65ffff0000ff0065ffffffffffff67ffff0000ffff0000861666ff0000ffff000085161760101c16941691161760101b161767ffffffff0000000063ffffffff8260201c169160201b166001600160401b0360c01b911760c01b1690565b90610e83565b91516110806040611078610f58602085015163ffffffff1690565b920151610e6a565b90610ebc565b94610ef4565b940151610e6a565b90610ef4565b604051906110a78261010b565b60606080835f81525f60208201525f60408201525f838201520152565b604051906110d1826100d0565b60606020835f81520152565b6040519061012082018281106001600160401b038211176100eb576040525f6101008382815261110b6110c4565b602082015282604082015261111e6110c4565b60608201528260808201526111316110c4565b60a08201528260c0820152606060e08201520152565b906111518261024a565b61115e6040519182610141565b828152809261116f601f199161024a565b01905f5b82811061117f57505050565b60209061118a6110dd565b82828501015201611173565b61119e61109a565b506111a7610182565b9081525f60208201526111c16111bc82611308565b6114db565b906111cb816115cb565b6111d76111bc83611308565b6111e36111bc84611308565b916111ed846115cb565b6111f681611147565b945f5b8281106112255750505061120b610191565b948552602085015260408401526060830152608082015290565b60019061123183611755565b60ff61123b6110dd565b9116806112675750600160c08201525b611255828a6108b1565b5261126081896108b1565b50016111f9565b6004810361128b575060016040820152611280846117d2565b60608201525b61124b565b600581036112ae5750600160808201526112a4846117d2565b60a082015261124b565b600681036112ce5750600181526112c4846117d2565b602082015261124b565b60080361128657600161010082015261124b565b634e487b7160e01b5f52601160045260245ffd5b9190820180921161130357565b6112e2565b6020810180516020810180911161130357825151106100b8576020915182825182010192839101116113035761133e6020610261565b9161134c6040519384610141565b6020835261135a6020610261565b6020840190601f19013682379060205b60208110156113b9578061139a57505f19905b811990511690825116179052611395602082516112f6565b905290565b6113ae6113a96113b39261193c565b6119cf565b61194a565b9061137d565b909182518152602081018091116113035791602081018091116113035790601f1981019081111561136a576112e2565b919060208301805182810180911161130357845151106100b85781156114c3576020935184825182010194859101116113035761142582610261565b916114336040519384610141565b80835261143f81610261565b602084019590601f19013687378195905b6020871015611494576113959394959680155f1461147f57505f19905b518251821691191617905282516112f6565b6113ae6113a961148e9261193c565b9061146d565b9081518152602081018091116113035790602081018091116113035795601f1981019081116113035795611450565b505090506040516114d5602082610141565b5f815290565b60208151106114eb576020015190565b60405162461bcd60e51b8152602060048201526024808201527f42797465733a3a20746f427974657333323a206461746120697320746f20736860448201526337b93a1760e11b6064820152608490fd5b60ff60049116019060ff821161130357565b1561155557565b60405162461bcd60e51b815260206004820152602860248201527f756e657870656374656420707265666978206465636f64696e6720436f6d706160448201526731ba1e2ab4b73a1f60c11b6064820152608490fd5b906001600160401b03809116911601906001600160401b03821161130357565b6115d481611755565b60038116806115f057506107b4915060021c603f165b60ff1690565b6001810361164157506116359061162f6115ea6116256116156115ea6107b497611755565b60061b67ffffffffffffffc01690565b9260021c603f1690565b906115ab565b6001600160401b031690565b600281036116c057506116b7906116aa60ff8461169b826116646107b498611755565b958161168a8161167c61167688611755565b97611755565b991660081b63ffffff001690565b911617921660101b63ffff00001690565b17921660181b63ff0000001690565b1760021c633fffffff1690565b63ffffffff1690565b6003036116ff576107b49160ff6116e66116e16116fa94603f9060021c1690565b61153c565b16906116f5600883111561154e565b6113e9565b611958565b60405162461bcd60e51b815260206004820152601a60248201527f436f64652073686f756c6420626520756e726561636861626c650000000000006044820152606490fd5b9081518110156108c5570160200190565b6020810190815160018101809111611303578151511061179e575181516001600160f81b0319916117869190611744565b511660f81c9080519060018201809211611303575290565b60405162461bcd60e51b815260206004820152600c60248201526b4f7574206f662072616e676560a01b6044820152606490fd5b6117da6110c4565b50602081019081516004810180911161130357815151106100b85760209181518382518201019384910111611303576118136004610261565b926118216040519485610141565b6004845261182f6004610261565b6020850190601f19013682379060045b602081101561190c57806118f757505f19905b81199051169082511617905261186a600482516112f6565b90525f915f905b600482106118b15750508061188861188e926115cb565b906113e9565b6118a9611899610182565b6001600160e01b03199093168352565b602082015290565b90926001600160f81b03196118c68584611744565b5116908460031b9185830460081486151715611303576001926001600160e01b0319918216901c1617930190611871565b6113ae6113a96119069261193c565b90611852565b909182518152602081018091116113035791602081018091116113035790601f1981019081111561183f576112e2565b602003906020821161130357565b5f1981019190821161130357565b80515f91815b61196757505090565b90915f1983018381116113035761197e8184611744565b5160f81c90600381901b906001600160fd1b038116036113035760ff8111611303576001901b90818102918183041490151715611303576119be916112f6565b918015611303575f1901908161195e565b601f8111611303576101000a9056fea264697066735822122016aa4d8047b1ad8f3df8cf9c0bc211c3e8c46005ba9e6d745f3404819a766f5a64736f6c634300081e0033

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

00000000000000000000000065b299f6d365f34a04b67f602b89f6fab094a01200468fb8911ecec00d7fd724627ea49172c901dfe0af8749b0af7a90c33e1948

-----Decoded View---------------
Arg [0] : verifier (address): 0x65B299f6d365F34a04B67f602B89f6Fab094a012
Arg [1] : verificationKey (bytes32): 0x00468fb8911ecec00d7fd724627ea49172c901dfe0af8749b0af7a90c33e1948

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000065b299f6d365f34a04b67f602b89f6fab094a012
Arg [1] : 00468fb8911ecec00d7fd724627ea49172c901dfe0af8749b0af7a90c33e1948


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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