false
false
0
The new Blockscout UI is now open source! Learn how to deploy it here

Contract Address Details

0xf88Ef5437749A225621101BE8C1BE1A0cE967758

Contract Name
LibInboxSetup
Creator
0x4e59b4–b4956c at 0xecd9c7–8b06d4
Balance
0 ETH
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
8500
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
LibInboxSetup




Optimization enabled
true
Compiler version
v0.8.30+commit.73712a01




Optimization runs
200
EVM Version
prague




Verified at
2025-12-15T12:39:39.509136Z

contracts/layer1/core/libs/LibInboxSetup.sol

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

import { IInbox } from "../iface/IInbox.sol";
import { LibHashOptimized } from "./LibHashOptimized.sol";

/// @title LibInboxSetup
/// @notice Library for Inbox setup code (constructor validation, activation).
/// @dev Using public functions in a library forces external linking, reducing deployment size
///      of the main contract at the cost of a small runtime gas overhead for the DELEGATECALL.
/// @custom:security-contact security@taiko.xyz
library LibInboxSetup {
    // ---------------------------------------------------------------
    // Public Functions (externally linked)
    // ---------------------------------------------------------------

    /// @dev The time window during which activate() can be called after the first activation.
    uint256 public constant ACTIVATION_WINDOW = 2 hours;

    /// @dev Validates the Inbox configuration parameters.
    /// @param _config The configuration to validate.
    function validateConfig(IInbox.Config memory _config) public pure {
        // Validate in the order fields are defined in Config struct
        require(_config.codec != address(0), CodecZero());
        require(_config.proofVerifier != address(0), ProofVerifierZero());
        require(_config.proposerChecker != address(0), ProposerCheckerZero());
        require(_config.signalService != address(0), SignalServiceZero());
        require(_config.provingWindow != 0, ProvingWindowZero());
        require(_config.ringBufferSize > 1, RingBufferSizeTooSmall());
        require(_config.basefeeSharingPctg <= 100, BasefeeSharingPctgTooLarge());
        require(_config.minForcedInclusionCount != 0, MinForcedInclusionCountZero());
        require(_config.forcedInclusionFeeInGwei != 0, ForcedInclusionFeeInGweiZero());
        require(
            _config.forcedInclusionFeeDoubleThreshold != 0, ForcedInclusionFeeDoubleThresholdZero()
        );
        require(
            _config.permissionlessInclusionMultiplier > 1,
            PermissionlessInclusionMultiplierTooSmall()
        );
    }

    /// @dev Validates activation and computes the initial state for inbox activation.
    /// @param _lastPacayaBlockHash The block hash of the last Pacaya block.
    /// @param _activationTimestamp The current activation timestamp (0 if not yet activated).
    /// @return activationTimestamp_ The activation timestamp to use.
    /// @return state_ The initial CoreState.
    /// @return derivation_ The genesis derivation.
    /// @return proposal_ The genesis proposal.
    /// @return genesisProposalHash_ The hash of the genesis proposal (id=0).
    function activate(
        bytes32 _lastPacayaBlockHash,
        uint48 _activationTimestamp
    )
        public
        view
        returns (
            uint48 activationTimestamp_,
            IInbox.CoreState memory state_,
            IInbox.Derivation memory derivation_,
            IInbox.Proposal memory proposal_,
            bytes32 genesisProposalHash_
        )
    {
        // Validate activation parameters
        require(_lastPacayaBlockHash != 0, InvalidLastPacayaBlockHash());
        if (_activationTimestamp == 0) {
            activationTimestamp_ = uint48(block.timestamp);
        } else {
            require(
                block.timestamp <= ACTIVATION_WINDOW + _activationTimestamp,
                ActivationPeriodExpired()
            );
            activationTimestamp_ = _activationTimestamp;
        }

        // Set lastProposalBlockId to 1 to ensure the first proposal happens at block 2 or later.
        // This prevents reading blockhash(0) in propose(), which would return 0x0 and create
        // an invalid origin block hash. The EVM hardcodes blockhash(0) to 0x0, so we must
        // ensure proposals never reference the genesis block.
        state_.nextProposalId = 1;
        state_.lastProposalBlockId = 1;
        state_.lastFinalizedTimestamp = uint48(block.timestamp);
        state_.lastFinalizedBlockHash = _lastPacayaBlockHash;

        proposal_.derivationHash = LibHashOptimized.hashDerivation(derivation_);
        genesisProposalHash_ = LibHashOptimized.hashProposal(proposal_);
    }

    // ---------------------------------------------------------------
    // Errors
    // ---------------------------------------------------------------

    error ActivationPeriodExpired();
    error BasefeeSharingPctgTooLarge();
    error CodecZero();
    error ForcedInclusionFeeDoubleThresholdZero();
    error ForcedInclusionFeeInGweiZero();
    error InvalidLastPacayaBlockHash();
    error MinForcedInclusionCountZero();
    error PermissionlessInclusionMultiplierTooSmall();
    error ProofVerifierZero();
    error ProposerCheckerZero();
    error ProvingWindowZero();
    error RingBufferSizeTooSmall();
    error SignalServiceZero();
}
        

contracts/layer1/core/iface/IInbox.sol

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

import { LibBlobs } from "../libs/LibBlobs.sol";
import { LibBonds } from "src/shared/libs/LibBonds.sol";

/// @title IInbox
/// @notice Interface for the Shasta inbox contracts
/// @custom:security-contact security@taiko.xyz
interface IInbox {
    /// @notice Configuration struct for Inbox constructor parameters
    struct Config {
        /// @notice The codec used for encoding and hashing
        address codec;
        /// @notice The proof verifier contract
        address proofVerifier;
        /// @notice The proposer checker contract
        address proposerChecker;
        /// @notice The prover whitelist contract (address(0) means no whitelist)
        address proverWhitelist;
        /// @notice The signal service contract address
        address signalService;
        /// @notice The proving window in seconds
        uint48 provingWindow;
        /// @notice Maximum delay allowed between consecutive proofs to still be on time.
        /// @dev Must be shorter than the expected proposal cadence to prevent backlog growth.
        uint48 maxProofSubmissionDelay;
        /// @notice The ring buffer size for storing proposal hashes
        uint256 ringBufferSize;
        /// @notice The percentage of basefee paid to coinbase
        uint8 basefeeSharingPctg;
        /// @notice The minimum number of forced inclusions that the proposer is forced to process
        /// if they are due
        uint256 minForcedInclusionCount;
        /// @notice The delay for forced inclusions measured in seconds
        uint16 forcedInclusionDelay;
        /// @notice The base fee for forced inclusions in Gwei used in dynamic fee calculation
        uint64 forcedInclusionFeeInGwei;
        /// @notice Queue size at which the fee doubles
        uint64 forcedInclusionFeeDoubleThreshold;
        /// @notice The minimum delay between checkpoints in seconds
        /// @dev Must be less than or equal to finalization grace period
        uint16 minCheckpointDelay;
        /// @notice The multiplier to determine when a forced inclusion is too old so that proposing
        /// becomes permissionless
        uint8 permissionlessInclusionMultiplier;
    }

    /// @notice Represents a source of derivation data within a Derivation
    struct DerivationSource {
        /// @notice Whether this source is from a forced inclusion.
        bool isForcedInclusion;
        /// @notice Blobs that contain the source's manifest data.
        LibBlobs.BlobSlice blobSlice;
    }

    /// @notice Contains derivation data for a proposal that is not needed during proving.
    /// @dev This data is hashed and stored in the Proposal struct to reduce calldata size.
    struct Derivation {
        /// @notice The L1 block number when the proposal was accepted.
        uint48 originBlockNumber;
        /// @notice The hash of the origin block.
        bytes32 originBlockHash;
        /// @notice The percentage of base fee paid to coinbase.
        uint8 basefeeSharingPctg;
        /// @notice Array of derivation sources, where each can be regular or forced inclusion.
        DerivationSource[] sources;
    }

    /// @notice Represents a proposal for L2 blocks.
    struct Proposal {
        /// @notice Unique identifier for the proposal.
        uint48 id;
        /// @notice The L1 block timestamp when the proposal was accepted.
        uint48 timestamp;
        /// @notice The timestamp of the last slot where the current preconfer can propose.
        uint48 endOfSubmissionWindowTimestamp;
        /// @notice Address of the proposer.
        address proposer;
        /// @notice Hash of the parent proposal (zero for genesis).
        bytes32 parentProposalHash;
        /// @notice Hash of the Derivation struct containing additional proposal data.
        bytes32 derivationHash;
    }

    /// @notice Represents the core state of the inbox.
    /// @dev All 5 uint48 fields (30 bytes) pack into a single storage slot.
    struct CoreState {
        /// @notice The next proposal ID to be assigned.
        uint48 nextProposalId;
        /// @notice The last L1 block ID where a proposal was made.
        uint48 lastProposalBlockId;
        /// @notice The ID of the last finalized proposal.
        uint48 lastFinalizedProposalId;
        /// @notice The timestamp when the last proposal was finalized.
        uint48 lastFinalizedTimestamp;
        /// @notice The timestamp when the last checkpoint was saved.
        /// @dev In genesis block, this is set to 0 to allow the first checkpoint to be saved.
        uint48 lastCheckpointTimestamp;
        /// @notice The block hash of the last finalized proposal.
        bytes32 lastFinalizedBlockHash;
    }

    /// @notice Input data for the propose function
    struct ProposeInput {
        /// @notice The deadline timestamp for transaction inclusion (0 = no deadline).
        uint48 deadline;
        /// @notice Blob reference for proposal data.
        LibBlobs.BlobReference blobReference;
        /// @notice The number of forced inclusions that the proposer wants to process.
        /// @dev This can be set to 0 if no forced inclusions are due, and there's none in the queue
        /// that he wants to include.
        uint8 numForcedInclusions;
    }

    /// @notice Transition data for a proposal used in prove
    struct Transition {
        /// @notice Address of the proposer.
        address proposer;
        /// @notice Address of the designated prover.
        address designatedProver;
        /// @notice Timestamp of the proposal.
        uint48 timestamp;
        /// @notice end block hash for the proposal.
        bytes32 blockHash;
    }

    /// @notice Commitment data that the prover commits to when submitting a proof.
    struct Commitment {
        /// @notice The ID of the first proposal being proven.
        uint48 firstProposalId;
        /// @notice The checkpoint hash of the parent of the first proposal, this is used
        /// to verify checkpoint continuity in the proof.
        bytes32 firstProposalParentBlockHash;
        /// @notice The hash of the last proposal being proven.
        bytes32 lastProposalHash;
        /// @notice The actual prover who generated the proof.
        address actualProver;
        /// @notice The block number for the end L2 block in this proposal.
        uint48 endBlockNumber;
        /// @notice The state root for the end L2 block in this proposal.
        bytes32 endStateRoot;
        /// @notice Array of transitions for each proposal in the proof range.
        Transition[] transitions;
    }

    /// @notice Input data for the prove function.
    /// @dev This struct contains two categories of data:
    ///      1. Commitment data - What the prover is actually proving. This must be fully
    ///         determined before proof generation and is the only input to the prover's
    ///         guest program.
    ///      2. Usage options - Parameters that can be decided after proof generation
    ///         (e.g., whether to proactively write a checkpoint). The prover system can
    ///         choose or adjust these options using additional data during or after
    ///         proof generation.
    struct ProveInput {
        /// @notice The commitment data that the proof verifies.
        Commitment commitment;
        /// @notice Whether to force syncing the last checkpoint even if the minimum
        /// delay has not passed.
        /// @dev This allows checkpoint synchronization ahead of schedule.
        bool forceCheckpointSync;
    }

    /// @notice Payload data emitted in the Proposed event
    struct ProposedEventPayload {
        /// @notice The proposal that was created.
        Proposal proposal;
        /// @notice The derivation data for the proposal.
        Derivation derivation;
    }

    /// @notice Payload data emitted in the Proved event
    struct ProvedEventPayload {
        ProveInput input;
    }

    // ---------------------------------------------------------------
    // Events
    // ---------------------------------------------------------------

    /// @notice Emitted when a new proposal is proposed.
    /// @param data The encoded ProposedEventPayload
    event Proposed(bytes data);

    /// @notice Emitted when a proof is submitted
    /// @param data The encoded ProvedEventPayload
    event Proved(bytes data);

    /// @notice Emitted when a bond instruction is signaled to L2
    /// @param proposalId The proposal ID that triggered the bond instruction
    /// @param bondInstruction The encoded bond instruction
    event BondInstructionCreated(
        uint48 indexed proposalId, LibBonds.BondInstruction bondInstruction
    );

    event DebugHash(uint8 index, bytes32 hash);
    event DebugNumber(uint8 index, uint48 number);
    event DebugAddress(uint8 index, address addr);

    // ---------------------------------------------------------------
    // External Transactional Functions
    // ---------------------------------------------------------------

    /// @notice Proposes new L2 blocks and forced inclusions to the rollup using blobs for DA.
    /// @param _lookahead Encoded data forwarded to the proposer checker (i.e. lookahead payloads).
    /// @param _data The encoded ProposeInput struct.
    function propose(bytes calldata _lookahead, bytes calldata _data) external;

    /// @notice Verifies a batch proof covering multiple consecutive proposals and finalizes them.
    /// @param _data The encoded ProveInput struct.
    /// @param _proof The validity proof for the batch of proposals.
    function prove(bytes calldata _data, bytes calldata _proof) external;

    // ---------------------------------------------------------------
    // External View Functions
    // ---------------------------------------------------------------

    /// @notice Returns the configuration parameters of the Inbox contract
    /// @return config_ The configuration struct containing all immutable parameters
    function getConfig() external view returns (Config memory config_);

    /// @notice Returns the current core state.
    /// @return The core state struct.
    function getCoreState() external view returns (CoreState memory);

    /// @notice Returns the proposal hash for a given proposal ID.
    /// @param _proposalId The proposal ID to look up.
    /// @return proposalHash_ The hash stored at the proposal's ring buffer slot.
    function getProposalHash(uint256 _proposalId) external view returns (bytes32 proposalHash_);
}
          

contracts/layer1/core/libs/LibBlobs.sol

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

/// @title LibBlobs
/// @notice Library for handling blobs.
/// @custom:security-contact security@taiko.xyz
library LibBlobs {
    // ---------------------------------------------------------------
    // Constants
    // ---------------------------------------------------------------
    uint256 internal constant FIELD_ELEMENT_BYTES = 32;
    uint256 internal constant BLOB_FIELD_ELEMENTS = 4096;
    uint256 internal constant BLOB_BYTES = BLOB_FIELD_ELEMENTS * FIELD_ELEMENT_BYTES;

    // ---------------------------------------------------------------
    // Structs
    // ---------------------------------------------------------------

    /// @notice Represents a segment of data that is stored in multiple consecutive blobs created
    /// in this transaction.
    struct BlobReference {
        /// @notice The starting index of the blob.
        uint16 blobStartIndex;
        /// @notice The number of blobs.
        uint16 numBlobs;
        /// @notice The field-element offset within the blob data.
        uint24 offset;
    }

    /// @notice Represents a frame of data that is stored in multiple blobs. Note the size is
    /// encoded as a bytes32 at the offset location.
    struct BlobSlice {
        /// @notice The blobs containing the proposal's content.
        bytes32[] blobHashes;
        /// @notice The byte offset of the proposal's content in the containing blobs.
        uint24 offset;
        /// @notice The timestamp when the frame was created.
        uint48 timestamp;
    }

    // ---------------------------------------------------------------
    // Functions
    // ---------------------------------------------------------------

    /// @dev Validates a blob locator and converts it to a blob slice.
    /// @param _blobReference The blob locator to validate.
    /// @return The blob slice.
    function validateBlobReference(BlobReference memory _blobReference)
        internal
        view
        returns (BlobSlice memory)
    {
        require(_blobReference.numBlobs > 0, NoBlobs());

        bytes32[] memory blobHashes = new bytes32[](_blobReference.numBlobs);
        for (uint256 i; i < _blobReference.numBlobs; ++i) {
            blobHashes[i] = blobhash(_blobReference.blobStartIndex + i);
            require(blobHashes[i] != 0, BlobNotFound());
        }

        return BlobSlice({
            blobHashes: blobHashes,
            offset: _blobReference.offset,
            timestamp: uint48(block.timestamp)
        });
    }

    // ---------------------------------------------------------------
    // Errors
    // ---------------------------------------------------------------

    error BlobNotFound();
    error NoBlobs();
}
          

contracts/layer1/core/libs/LibHashOptimized.sol

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

import { IInbox } from "../iface/IInbox.sol";
import { EfficientHashLib } from "solady/src/utils/EfficientHashLib.sol";

/// @title LibHashOptimized
/// @notice Optimized hashing functions using Solady's EfficientHashLib
/// @dev This library provides gas-optimized implementations of all hashing functions
///      used in the Inbox contract, replacing standard keccak256(abi.encode(...)) calls
///      with more efficient alternatives from Solady's EfficientHashLib.
/// @custom:security-contact security@taiko.xyz
library LibHashOptimized {
    // ---------------------------------------------------------------
    // Core Structure Hashing Functions
    // ---------------------------------------------------------------

    /// @notice Optimized hashing for Derivation structs
    /// @dev Manually constructs the ABI-encoded layout to avoid nested abi.encode calls
    /// @param _derivation The derivation to hash
    /// @return The hash of the derivation
    function hashDerivation(IInbox.Derivation memory _derivation) internal pure returns (bytes32) {
        unchecked {
            IInbox.DerivationSource[] memory sources = _derivation.sources;
            uint256 sourcesLength = sources.length;

            // Base words:
            // [0] offset to tuple head (0x20)
            // [1] originBlockNumber
            // [2] originBlockHash
            // [3] basefeeSharingPctg
            // [4] offset to sources (0x80)
            // [5] sources length
            uint256 totalWords = 6 + sourcesLength;

            // Each source contributes: element head (2) + blobSlice head (3) + blobHashes
            // length (1) + blobHashes entries
            for (uint256 i; i < sourcesLength; ++i) {
                totalWords += 6 + sources[i].blobSlice.blobHashes.length;
            }

            bytes32[] memory buffer = EfficientHashLib.malloc(totalWords);

            EfficientHashLib.set(buffer, 0, bytes32(uint256(0x20)));
            EfficientHashLib.set(buffer, 1, bytes32(uint256(_derivation.originBlockNumber)));
            EfficientHashLib.set(buffer, 2, _derivation.originBlockHash);
            EfficientHashLib.set(buffer, 3, bytes32(uint256(_derivation.basefeeSharingPctg)));
            EfficientHashLib.set(buffer, 4, bytes32(uint256(0x80)));
            EfficientHashLib.set(buffer, 5, bytes32(sourcesLength));

            uint256 offsetsBase = 6;
            uint256 dataCursor = offsetsBase + sourcesLength;

            for (uint256 i; i < sourcesLength; ++i) {
                IInbox.DerivationSource memory source = sources[i];
                EfficientHashLib.set(
                    buffer, offsetsBase + i, bytes32((dataCursor - offsetsBase) << 5)
                );

                // DerivationSource head
                EfficientHashLib.set(
                    buffer, dataCursor, bytes32(uint256(source.isForcedInclusion ? 1 : 0))
                );
                EfficientHashLib.set(buffer, dataCursor + 1, bytes32(uint256(0x40)));

                // BlobSlice head
                uint256 blobSliceBase = dataCursor + 2;
                EfficientHashLib.set(buffer, blobSliceBase, bytes32(uint256(0x60)));
                EfficientHashLib.set(
                    buffer, blobSliceBase + 1, bytes32(uint256(source.blobSlice.offset))
                );
                EfficientHashLib.set(
                    buffer, blobSliceBase + 2, bytes32(uint256(source.blobSlice.timestamp))
                );

                // Blob hashes array
                bytes32[] memory blobHashes = source.blobSlice.blobHashes;
                uint256 blobHashesLength = blobHashes.length;
                uint256 blobHashesBase = blobSliceBase + 3;
                EfficientHashLib.set(buffer, blobHashesBase, bytes32(blobHashesLength));

                for (uint256 j; j < blobHashesLength; ++j) {
                    EfficientHashLib.set(buffer, blobHashesBase + 1 + j, blobHashes[j]);
                }

                dataCursor = blobHashesBase + 1 + blobHashesLength;
            }

            bytes32 result = EfficientHashLib.hash(buffer);
            EfficientHashLib.free(buffer);
            return result;
        }
    }

    /// @notice Optimized hashing for Proposal structs
    /// @dev Uses efficient multi-field hashing for all proposal fields
    /// @param _proposal The proposal to hash
    /// @return The hash of the proposal
    function hashProposal(IInbox.Proposal memory _proposal) internal pure returns (bytes32) {
        bytes32[] memory buffer = EfficientHashLib.malloc(6);

        EfficientHashLib.set(buffer, 0, bytes32(uint256(_proposal.id)));
        EfficientHashLib.set(buffer, 1, bytes32(uint256(_proposal.timestamp)));
        EfficientHashLib.set(buffer, 2, bytes32(uint256(_proposal.endOfSubmissionWindowTimestamp)));
        EfficientHashLib.set(buffer, 3, bytes32(uint256(uint160(_proposal.proposer))));
        EfficientHashLib.set(buffer, 4, _proposal.parentProposalHash);
        EfficientHashLib.set(buffer, 5, _proposal.derivationHash);

        bytes32 result = EfficientHashLib.hash(buffer);
        EfficientHashLib.free(buffer);
        return result;
    }

    /// @notice Optimized hashing for commitment data.
    /// @param _commitment The commitment data to hash.
    /// @return The hash of the commitment.
    function hashCommitment(IInbox.Commitment memory _commitment) internal pure returns (bytes32) {
        unchecked {
            IInbox.Transition[] memory transitions = _commitment.transitions;
            uint256 transitionsLength = transitions.length;

            // Commitment layout (abi.encode):
            // [0] offset to commitment (0x20)
            //
            // Commitment static section (starts at word 1):
            // [1] firstProposalId
            // [2] firstProposalParentBlockHash
            // [3] lastProposalHash
            // [4] actualProver
            // [5] endBlockNumber
            // [6] endStateRoot
            // [7] offset to transitions (0xe0)
            //
            // Transitions array (starts at word 8):
            // [8] length
            // [9...] transition elements (4 words each)
            uint256 totalWords = 9 + transitionsLength * 4;

            bytes32[] memory buffer = EfficientHashLib.malloc(totalWords);

            // Top-level head
            EfficientHashLib.set(buffer, 0, bytes32(uint256(0x20)));

            // Commitment static fields
            EfficientHashLib.set(buffer, 1, bytes32(uint256(_commitment.firstProposalId)));
            EfficientHashLib.set(buffer, 2, _commitment.firstProposalParentBlockHash);
            EfficientHashLib.set(buffer, 3, _commitment.lastProposalHash);
            EfficientHashLib.set(buffer, 4, bytes32(uint256(uint160(_commitment.actualProver))));
            EfficientHashLib.set(buffer, 5, bytes32(uint256(_commitment.endBlockNumber)));
            EfficientHashLib.set(buffer, 6, _commitment.endStateRoot);
            EfficientHashLib.set(buffer, 7, bytes32(uint256(0xe0)));

            // Transitions array
            EfficientHashLib.set(buffer, 8, bytes32(transitionsLength));

            uint256 base = 9;
            for (uint256 i; i < transitionsLength; ++i) {
                IInbox.Transition memory transition = transitions[i];
                EfficientHashLib.set(buffer, base, bytes32(uint256(uint160(transition.proposer))));
                EfficientHashLib.set(
                    buffer, base + 1, bytes32(uint256(uint160(transition.designatedProver)))
                );
                EfficientHashLib.set(buffer, base + 2, bytes32(uint256(transition.timestamp)));
                EfficientHashLib.set(buffer, base + 3, transition.blockHash);
                base += 4;
            }

            bytes32 result = EfficientHashLib.hash(buffer);
            EfficientHashLib.free(buffer);
            return result;
        }
    }
}
          

contracts/shared/libs/LibBonds.sol

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

/// @title LibBonds
/// @notice Library for managing bond instructions
/// @custom:security-contact security@taiko.xyz
library LibBonds {
    // ---------------------------------------------------------------
    // Enums
    // ---------------------------------------------------------------

    enum BondType {
        NONE,
        LIVENESS
    }

    // ---------------------------------------------------------------
    // Structs
    // ---------------------------------------------------------------

    struct BondInstruction {
        uint48 proposalId;
        BondType bondType;
        address payer;
        address payee;
    }

    // ---------------------------------------------------------------
    // Functions
    // ---------------------------------------------------------------

    /// @dev Hashing for BondInstruction structs using keccak256 and abi.encode
    /// @dev This function is not optimized using EfficientHashLib for
    ///      gas savings because it's not expected to be called frequently.
    /// @param _bondInstruction The bond instruction to hash
    /// @return The hash of the bond instruction
    function hashBondInstruction(BondInstruction memory _bondInstruction)
        internal
        pure
        returns (bytes32)
    {
        /// forge-lint: disable-next-line(asm-keccak256)
        return keccak256(abi.encode(_bondInstruction));
    }
}
          

node_modules/solady/src/utils/EfficientHashLib.sol

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

/// @notice Library for efficiently performing keccak256 hashes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EfficientHashLib.sol)
/// @dev To avoid stack-too-deep, you can use:
/// ```
/// bytes32[] memory buffer = EfficientHashLib.malloc(10);
/// EfficientHashLib.set(buffer, 0, value0);
/// ..
/// EfficientHashLib.set(buffer, 9, value9);
/// bytes32 finalHash = EfficientHashLib.hash(buffer);
/// ```
library EfficientHashLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               MALLOC-LESS HASHING OPERATIONS               */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `keccak256(abi.encode(v0))`.
    function hash(bytes32 v0) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            result := keccak256(0x00, 0x20)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0))`.
    function hash(uint256 v0) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            result := keccak256(0x00, 0x20)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1))`.
    function hash(bytes32 v0, bytes32 v1) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            mstore(0x20, v1)
            result := keccak256(0x00, 0x40)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1))`.
    function hash(uint256 v0, uint256 v1) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            mstore(0x20, v1)
            result := keccak256(0x00, 0x40)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            result := keccak256(m, 0x60)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
    function hash(uint256 v0, uint256 v1, uint256 v2) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            result := keccak256(m, 0x60)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            result := keccak256(m, 0x80)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            result := keccak256(m, 0x80)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            result := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            result := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4, bytes32 v5)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            result := keccak256(m, 0xc0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4, uint256 v5)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            result := keccak256(m, 0xc0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            result := keccak256(m, 0xe0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            result := keccak256(m, 0xe0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            result := keccak256(m, 0x100)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            result := keccak256(m, 0x100)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            result := keccak256(m, 0x120)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            result := keccak256(m, 0x120)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            result := keccak256(m, 0x140)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            result := keccak256(m, 0x140)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            result := keccak256(m, 0x160)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            result := keccak256(m, 0x160)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            result := keccak256(m, 0x180)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            result := keccak256(m, 0x180)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11,
        bytes32 v12
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            result := keccak256(m, 0x1a0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11,
        uint256 v12
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            result := keccak256(m, 0x1a0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11,
        bytes32 v12,
        bytes32 v13
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            mstore(add(m, 0x1a0), v13)
            result := keccak256(m, 0x1c0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11,
        uint256 v12,
        uint256 v13
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            mstore(add(m, 0x1a0), v13)
            result := keccak256(m, 0x1c0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*             BYTES32 BUFFER HASHING OPERATIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `keccak256(abi.encode(buffer[0], .., buffer[buffer.length - 1]))`.
    function hash(bytes32[] memory buffer) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(add(buffer, 0x20), shl(5, mload(buffer)))
        }
    }

    /// @dev Sets `buffer[i]` to `value`, without a bounds check.
    /// Returns the `buffer` for function chaining.
    function set(bytes32[] memory buffer, uint256 i, bytes32 value)
        internal
        pure
        returns (bytes32[] memory)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(add(buffer, shl(5, add(1, i))), value)
        }
        return buffer;
    }

    /// @dev Sets `buffer[i]` to `value`, without a bounds check.
    /// Returns the `buffer` for function chaining.
    function set(bytes32[] memory buffer, uint256 i, uint256 value)
        internal
        pure
        returns (bytes32[] memory)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(add(buffer, shl(5, add(1, i))), value)
        }
        return buffer;
    }

    /// @dev Returns `new bytes32[](n)`, without zeroing out the memory.
    function malloc(uint256 n) internal pure returns (bytes32[] memory buffer) {
        /// @solidity memory-safe-assembly
        assembly {
            buffer := mload(0x40)
            mstore(buffer, n)
            mstore(0x40, add(shl(5, add(1, n)), buffer))
        }
    }

    /// @dev Frees memory that has been allocated for `buffer`.
    /// No-op if `buffer.length` is zero, or if new memory has been allocated after `buffer`.
    function free(bytes32[] memory buffer) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(buffer)
            mstore(shl(6, lt(iszero(n), eq(add(shl(5, add(1, n)), buffer), mload(0x40)))), buffer)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      EQUALITY CHECKS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `a == abi.decode(b, (bytes32))`.
    function eq(bytes32 a, bytes memory b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(eq(0x20, mload(b)), eq(a, mload(add(b, 0x20))))
        }
    }

    /// @dev Returns `abi.decode(a, (bytes32)) == a`.
    function eq(bytes memory a, bytes32 b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(eq(0x20, mload(a)), eq(b, mload(add(a, 0x20))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               BYTE SLICE HASHING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function hash(bytes memory b, uint256 start, uint256 end)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            end := xor(end, mul(xor(end, n), lt(n, end)))
            start := xor(start, mul(xor(start, n), lt(n, start)))
            result := keccak256(add(add(b, 0x20), start), mul(gt(end, start), sub(end, start)))
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
    function hash(bytes memory b, uint256 start) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            start := xor(start, mul(xor(start, n), lt(n, start)))
            result := keccak256(add(add(b, 0x20), start), mul(gt(n, start), sub(n, start)))
        }
    }

    /// @dev Returns the keccak256 of the bytes.
    function hash(bytes memory b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(add(b, 0x20), mload(b))
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function hashCalldata(bytes calldata b, uint256 start, uint256 end)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(end, start), sub(end, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := keccak256(mload(0x40), n)
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
    function hashCalldata(bytes calldata b, uint256 start) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(b.length, start), sub(b.length, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := keccak256(mload(0x40), n)
        }
    }

    /// @dev Returns the keccak256 of the bytes.
    function hashCalldata(bytes calldata b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            calldatacopy(mload(0x40), b.offset, b.length)
            result := keccak256(mload(0x40), b.length)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      SHA2-256 HELPERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `sha256(abi.encode(b))`. Yes, it's more efficient.
    function sha2(bytes32 b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, b)
            result := mload(staticcall(gas(), 2, 0x00, 0x20, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function sha2(bytes memory b, uint256 start, uint256 end)
        internal
        view
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            end := xor(end, mul(xor(end, n), lt(n, end)))
            start := xor(start, mul(xor(start, n), lt(n, start)))
            // forgefmt: disable-next-item
            result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
                mul(gt(end, start), sub(end, start)), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
    function sha2(bytes memory b, uint256 start) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            start := xor(start, mul(xor(start, n), lt(n, start)))
            // forgefmt: disable-next-item
            result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
                mul(gt(n, start), sub(n, start)), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the bytes.
    function sha2(bytes memory b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(staticcall(gas(), 2, add(b, 0x20), mload(b), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function sha2Calldata(bytes calldata b, uint256 start, uint256 end)
        internal
        view
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(end, start), sub(end, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
    function sha2Calldata(bytes calldata b, uint256 start) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(b.length, start), sub(b.length, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the bytes.
    function sha2Calldata(bytes calldata b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            calldatacopy(mload(0x40), b.offset, b.length)
            result := mload(staticcall(gas(), 2, mload(0x40), b.length, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }
}
          

Compiler Settings

{"viaIR":true,"remappings":["openzeppelin/=node_modules/@openzeppelin/","@openzeppelin/=node_modules/@openzeppelin/","@openzeppelin-upgrades/contracts/=node_modules/@openzeppelin/contracts-upgradeable/","@risc0/contracts/=node_modules/risc0-ethereum/contracts/src/","@solady/=node_modules/solady/","solady/src/=node_modules/solady/src/","solady/utils/=node_modules/solady/src/utils/","@optimism/=node_modules/optimism/","@sp1-contracts/=node_modules/sp1-contracts/contracts/","forge-std/=node_modules/forge-std/","@p256-verifier/contracts/=node_modules/p256-verifier/src/","@eth-fabric/urc/=node_modules/urc/src/","ds-test/=node_modules/ds-test/","src/=contracts/","test/=test/","script/=script/","optimism/=node_modules/optimism/","p256-verifier/=node_modules/p256-verifier/","risc0-ethereum/=node_modules/risc0-ethereum/","sp1-contracts/=node_modules/sp1-contracts/","urc/=node_modules/urc/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{"contracts/layer1/core/libs/LibInboxSetup.sol":{"LibInboxSetup":"0xf88Ef5437749A225621101BE8C1BE1A0cE967758"},"contracts/layer1/core/libs/LibForcedInclusion.sol":{"LibForcedInclusion":"0xd1a27F331c17eD8Cbb6DAbce67A42d6b8a6B0e14"}},"evmVersion":"prague"}
              

Contract ABI

[{"type":"error","name":"ActivationPeriodExpired","inputs":[]},{"type":"error","name":"BasefeeSharingPctgTooLarge","inputs":[]},{"type":"error","name":"CodecZero","inputs":[]},{"type":"error","name":"ForcedInclusionFeeDoubleThresholdZero","inputs":[]},{"type":"error","name":"ForcedInclusionFeeInGweiZero","inputs":[]},{"type":"error","name":"InvalidLastPacayaBlockHash","inputs":[]},{"type":"error","name":"MinForcedInclusionCountZero","inputs":[]},{"type":"error","name":"PermissionlessInclusionMultiplierTooSmall","inputs":[]},{"type":"error","name":"ProofVerifierZero","inputs":[]},{"type":"error","name":"ProposerCheckerZero","inputs":[]},{"type":"error","name":"ProvingWindowZero","inputs":[]},{"type":"error","name":"RingBufferSizeTooSmall","inputs":[]},{"type":"error","name":"SignalServiceZero","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"ACTIVATION_WINDOW","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint48","name":"activationTimestamp_","internalType":"uint48"},{"type":"tuple","name":"state_","internalType":"struct IInbox.CoreState","components":[{"type":"uint48","name":"nextProposalId","internalType":"uint48"},{"type":"uint48","name":"lastProposalBlockId","internalType":"uint48"},{"type":"uint48","name":"lastFinalizedProposalId","internalType":"uint48"},{"type":"uint48","name":"lastFinalizedTimestamp","internalType":"uint48"},{"type":"uint48","name":"lastCheckpointTimestamp","internalType":"uint48"},{"type":"bytes32","name":"lastFinalizedBlockHash","internalType":"bytes32"}]},{"type":"tuple","name":"derivation_","internalType":"struct IInbox.Derivation","components":[{"type":"uint48","name":"originBlockNumber","internalType":"uint48"},{"type":"bytes32","name":"originBlockHash","internalType":"bytes32"},{"type":"uint8","name":"basefeeSharingPctg","internalType":"uint8"},{"type":"tuple[]","name":"sources","internalType":"struct IInbox.DerivationSource[]","components":[{"type":"bool","name":"isForcedInclusion","internalType":"bool"},{"type":"tuple","name":"blobSlice","internalType":"struct LibBlobs.BlobSlice","components":[{"type":"bytes32[]","name":"blobHashes","internalType":"bytes32[]"},{"type":"uint24","name":"offset","internalType":"uint24"},{"type":"uint48","name":"timestamp","internalType":"uint48"}]}]}]},{"type":"tuple","name":"proposal_","internalType":"struct IInbox.Proposal","components":[{"type":"uint48","name":"id","internalType":"uint48"},{"type":"uint48","name":"timestamp","internalType":"uint48"},{"type":"uint48","name":"endOfSubmissionWindowTimestamp","internalType":"uint48"},{"type":"address","name":"proposer","internalType":"address"},{"type":"bytes32","name":"parentProposalHash","internalType":"bytes32"},{"type":"bytes32","name":"derivationHash","internalType":"bytes32"}]},{"type":"bytes32","name":"genesisProposalHash_","internalType":"bytes32"}],"name":"activate","inputs":[{"type":"bytes32","name":"_lastPacayaBlockHash","internalType":"bytes32"},{"type":"uint48","name":"_activationTimestamp","internalType":"uint48"}]},{"type":"function","stateMutability":"pure","outputs":[],"name":"validateConfig","inputs":[{"type":"tuple","name":"_config","internalType":"struct IInbox.Config","components":[{"type":"address","name":"codec","internalType":"address"},{"type":"address","name":"proofVerifier","internalType":"address"},{"type":"address","name":"proposerChecker","internalType":"address"},{"type":"address","name":"proverWhitelist","internalType":"address"},{"type":"address","name":"signalService","internalType":"address"},{"type":"uint48","name":"provingWindow","internalType":"uint48"},{"type":"uint48","name":"maxProofSubmissionDelay","internalType":"uint48"},{"type":"uint256","name":"ringBufferSize","internalType":"uint256"},{"type":"uint8","name":"basefeeSharingPctg","internalType":"uint8"},{"type":"uint256","name":"minForcedInclusionCount","internalType":"uint256"},{"type":"uint16","name":"forcedInclusionDelay","internalType":"uint16"},{"type":"uint64","name":"forcedInclusionFeeInGwei","internalType":"uint64"},{"type":"uint64","name":"forcedInclusionFeeDoubleThreshold","internalType":"uint64"},{"type":"uint16","name":"minCheckpointDelay","internalType":"uint16"},{"type":"uint8","name":"permissionlessInclusionMultiplier","internalType":"uint8"}]}]}]
              

Contract Creation Code

Verify & Publish
0x60808060405234601957610885908161001e823930815050f35b5f80fdfe6080806040526004361015610012575f80fd5b5f3560e01c90816338ff1c38146107d15750806391da2ffe146105205763f741c8cc1461003d575f80fd5b604036600319011261051c5760043560243565ffffffffffff81169081810361051c576100686107e6565b92604051916080830183811067ffffffffffffffff821117610508576040525f835260208301915f835260408401915f83526060850190606082526100ab6107e6565b9683156104f957806104bd57505065ffffffffffff4216965b60018152602081019660018852606082019265ffffffffffff4216845260a083019485528051958651806006019788915f5b81811061049d57506040518a819b825260010160051b0160405260208a01926020845265ffffffffffff8d511660408c01528b5160608c015260ff85511660808c0152608060a08c01528160c08c0152918a5f935b8385106103c65750925050505160051b90209661017a908051604051828260010160051b011490151060061b52565b60a0830196875260405197600689528860e001604052835165ffffffffffff169660208a019788526020850195865165ffffffffffff1660408c0152604086019d8e5165ffffffffffff1660608d015260608701988c600160a01b600190038b51169060800152608088019a8d8c519060a001528d8d519060c001528d5160051b90209c61021a908051604051828260010160051b011490151060061b52565b6040519e8f9265ffffffffffff168352835165ffffffffffff1660208401525165ffffffffffff166040830152604083015165ffffffffffff1660608301525165ffffffffffff1690608001526080015165ffffffffffff1660a08d01525160c08c015260e08b016101e090526102608b01995165ffffffffffff166101e08c0152516102008b01525160ff166102208a0152519661024089016080905287518091526102808901908060051b8a016102800198602001915f905b82821061032d57505050509765ffffffffffff8092818a9b51166101008b01525116610120890152511661014087015260018060a01b0390511661016086015251610180850152516101a08401526101c08301520390f35b9091929961027f198c820301825260208b518051151583520151906040602082015260a0810191805192606060408401528351809152602060c084019401905f905b8082106103ae57505050600192602092608065ffffffffffff60408562ffffff88809801511660608601520151169101529c01920192019092916102d5565b9091946020806001928851815201960192019061036f565b60206103d28685610827565b516005198301600590811b6007890190911b8501528051156104955760ff60015b168360010160051b85015260406002840160051b85015260606003840160051b8501520162ffffff602082510151166004830160051b84015265ffffffffffff604082510151166005830160051b8401525151805180936006840160051b01528d5f905b8482106104735750505060019160069101019301928b9061014b565b906001916104818285610827565b519060078387010160051b0152018e610457565b60ff5f6103f3565b99600660019160206104af8e87610827565b510151515101019a016100f6565b611c200180611c20116104e55742116104d657966100c4565b636f6dd95d60e01b5f5260045ffd5b634e487b7160e01b5f52601160045260245ffd5b630b17ad8f60e01b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b6101e036600319011261051c576040516101e0810181811067ffffffffffffffff821117610508576040526004356001600160a01b0381169081810361051c5782526024356001600160a01b038116810361051c57602083019081526044356001600160a01b038116810361051c57604084019081526064356001600160a01b038116810361051c5760608501526084356001600160a01b038116810361051c576080850190815260a43565ffffffffffff8116810361051c5760a0860190815260c43565ffffffffffff8116810361051c5760c087015260e086019060e4358252610104359260ff8416840361051c5761010088019384526101208801946101243586526101443561ffff8116810361051c576101408a0152610164359667ffffffffffffffff8816880361051c576101608a01978852610184359867ffffffffffffffff8a168a0361051c576101808b01998a526101a43561ffff8116810361051c576101a08c01526101c4359a60ff8c168c0361051c576101c0019a8b52156107c257516001600160a01b0316156107b357516001600160a01b0316156107a457516001600160a01b031615610795575165ffffffffffff1615610786576001905111156107775760ff606491511611610768575115610759575167ffffffffffffffff161561074a575167ffffffffffffffff161561073b5760ff6001915116111561072c57005b6341a40d0d60e01b5f5260045ffd5b632fe16a2760e11b5f5260045ffd5b63078eab8d60e51b5f5260045ffd5b6365e8d9b560e01b5f5260045ffd5b638ebe6ccb60e01b5f5260045ffd5b6319f723f160e01b5f5260045ffd5b63187c482d60e31b5f5260045ffd5b637a55052160e01b5f5260045ffd5b63674b146160e01b5f5260045ffd5b6362afc9c360e01b5f5260045ffd5b6318aa07c160e11b5f5260045ffd5b5f36600319011261051c5780611c2060209252f35b6040519060c0820182811067ffffffffffffffff821117610508576040525f60a0838281528260208201528260408201528260608201528260808201520152565b805182101561083b5760209160051b010190565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212209ce7244d3bc5b3903e3bba9b2d1ad85b2888dd2f7adfcee057f88d89be9aaf3764736f6c634300081e0033

Deployed ByteCode

0x6080806040526004361015610012575f80fd5b5f3560e01c90816338ff1c38146107d15750806391da2ffe146105205763f741c8cc1461003d575f80fd5b604036600319011261051c5760043560243565ffffffffffff81169081810361051c576100686107e6565b92604051916080830183811067ffffffffffffffff821117610508576040525f835260208301915f835260408401915f83526060850190606082526100ab6107e6565b9683156104f957806104bd57505065ffffffffffff4216965b60018152602081019660018852606082019265ffffffffffff4216845260a083019485528051958651806006019788915f5b81811061049d57506040518a819b825260010160051b0160405260208a01926020845265ffffffffffff8d511660408c01528b5160608c015260ff85511660808c0152608060a08c01528160c08c0152918a5f935b8385106103c65750925050505160051b90209661017a908051604051828260010160051b011490151060061b52565b60a0830196875260405197600689528860e001604052835165ffffffffffff169660208a019788526020850195865165ffffffffffff1660408c0152604086019d8e5165ffffffffffff1660608d015260608701988c600160a01b600190038b51169060800152608088019a8d8c519060a001528d8d519060c001528d5160051b90209c61021a908051604051828260010160051b011490151060061b52565b6040519e8f9265ffffffffffff168352835165ffffffffffff1660208401525165ffffffffffff166040830152604083015165ffffffffffff1660608301525165ffffffffffff1690608001526080015165ffffffffffff1660a08d01525160c08c015260e08b016101e090526102608b01995165ffffffffffff166101e08c0152516102008b01525160ff166102208a0152519661024089016080905287518091526102808901908060051b8a016102800198602001915f905b82821061032d57505050509765ffffffffffff8092818a9b51166101008b01525116610120890152511661014087015260018060a01b0390511661016086015251610180850152516101a08401526101c08301520390f35b9091929961027f198c820301825260208b518051151583520151906040602082015260a0810191805192606060408401528351809152602060c084019401905f905b8082106103ae57505050600192602092608065ffffffffffff60408562ffffff88809801511660608601520151169101529c01920192019092916102d5565b9091946020806001928851815201960192019061036f565b60206103d28685610827565b516005198301600590811b6007890190911b8501528051156104955760ff60015b168360010160051b85015260406002840160051b85015260606003840160051b8501520162ffffff602082510151166004830160051b84015265ffffffffffff604082510151166005830160051b8401525151805180936006840160051b01528d5f905b8482106104735750505060019160069101019301928b9061014b565b906001916104818285610827565b519060078387010160051b0152018e610457565b60ff5f6103f3565b99600660019160206104af8e87610827565b510151515101019a016100f6565b611c200180611c20116104e55742116104d657966100c4565b636f6dd95d60e01b5f5260045ffd5b634e487b7160e01b5f52601160045260245ffd5b630b17ad8f60e01b5f5260045ffd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b6101e036600319011261051c576040516101e0810181811067ffffffffffffffff821117610508576040526004356001600160a01b0381169081810361051c5782526024356001600160a01b038116810361051c57602083019081526044356001600160a01b038116810361051c57604084019081526064356001600160a01b038116810361051c5760608501526084356001600160a01b038116810361051c576080850190815260a43565ffffffffffff8116810361051c5760a0860190815260c43565ffffffffffff8116810361051c5760c087015260e086019060e4358252610104359260ff8416840361051c5761010088019384526101208801946101243586526101443561ffff8116810361051c576101408a0152610164359667ffffffffffffffff8816880361051c576101608a01978852610184359867ffffffffffffffff8a168a0361051c576101808b01998a526101a43561ffff8116810361051c576101a08c01526101c4359a60ff8c168c0361051c576101c0019a8b52156107c257516001600160a01b0316156107b357516001600160a01b0316156107a457516001600160a01b031615610795575165ffffffffffff1615610786576001905111156107775760ff606491511611610768575115610759575167ffffffffffffffff161561074a575167ffffffffffffffff161561073b5760ff6001915116111561072c57005b6341a40d0d60e01b5f5260045ffd5b632fe16a2760e11b5f5260045ffd5b63078eab8d60e51b5f5260045ffd5b6365e8d9b560e01b5f5260045ffd5b638ebe6ccb60e01b5f5260045ffd5b6319f723f160e01b5f5260045ffd5b63187c482d60e31b5f5260045ffd5b637a55052160e01b5f5260045ffd5b63674b146160e01b5f5260045ffd5b6362afc9c360e01b5f5260045ffd5b6318aa07c160e11b5f5260045ffd5b5f36600319011261051c5780611c2060209252f35b6040519060c0820182811067ffffffffffffffff821117610508576040525f60a0838281528260208201528260408201528260608201528260808201520152565b805182101561083b5760209160051b010190565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212209ce7244d3bc5b3903e3bba9b2d1ad85b2888dd2f7adfcee057f88d89be9aaf3764736f6c634300081e0033

External libraries