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

Contract Address Details

0xd1a27F331c17eD8Cbb6DAbce67A42d6b8a6B0e14

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




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




Optimization runs
200
EVM Version
prague




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

contracts/layer1/core/libs/LibForcedInclusion.sol

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

import { IForcedInclusionStore } from "../iface/IForcedInclusionStore.sol";
import { LibBlobs } from "../libs/LibBlobs.sol";
import { LibMath } from "src/shared/libs/LibMath.sol";

/// @title LibForcedInclusion
/// @dev Library for storing and managing forced inclusion requests. Forced inclusions
/// allow users to pay a fee to ensure their transactions are included in a block. The library
/// maintains a FIFO queue of inclusion requests.
/// @dev Inclusion delay is measured in seconds, since we don't have an easy way to get batch number
/// in the Shasta design.
/// @dev Forced inclusions are limited to 1 blob only, and one L2 block only(this and other protocol
/// constrains are enforced by the node and verified by the prover)
/// @custom:security-contact security@taiko.xyz
library LibForcedInclusion {
    using LibMath for uint48;
    using LibMath for uint256;

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

    /// @dev Storage for the forced inclusion queue. This struct uses 2 slots.
    /// @dev 2 slots used
    struct Storage {
        mapping(uint256 id => IForcedInclusionStore.ForcedInclusion inclusion) queue;
        /// @notice The index of the oldest forced inclusion in the queue. This is where items will
        /// be dequeued.
        uint48 head;
        /// @notice The index of the next free slot in the queue. This is where items will be
        /// enqueued.
        uint48 tail;
    }

    // ---------------------------------------------------------------
    //  Public Functions
    // ---------------------------------------------------------------

    /// @dev See `IForcedInclusionStore.saveForcedInclusion`
    function saveForcedInclusion(
        Storage storage $,
        uint64 _baseFeeInGwei,
        uint64 _feeDoubleThreshold,
        LibBlobs.BlobReference memory _blobReference
    )
        public
        returns (uint256 refund_)
    {
        LibBlobs.BlobSlice memory blobSlice = LibBlobs.validateBlobReference(_blobReference);
        require(blobSlice.blobHashes.length == 1, OnlySingleBlobAllowed());

        uint64 requiredFeeInGwei =
            getCurrentForcedInclusionFee($, _baseFeeInGwei, _feeDoubleThreshold);
        uint256 requiredFee = requiredFeeInGwei * 1 gwei;
        require(msg.value >= requiredFee, InsufficientFee());

        IForcedInclusionStore.ForcedInclusion memory inclusion =
            IForcedInclusionStore.ForcedInclusion({
                feeInGwei: requiredFeeInGwei, blobSlice: blobSlice
            });

        $.queue[$.tail++] = inclusion;

        emit IForcedInclusionStore.ForcedInclusionSaved(inclusion);

        // Calculate and return refund amount
        unchecked {
            refund_ = msg.value - requiredFee;
        }
    }

    /// @dev See `IForcedInclusionStore.getCurrentForcedInclusionFee`
    function getCurrentForcedInclusionFee(
        Storage storage $,
        uint64 _baseFeeInGwei,
        uint64 _feeDoubleThreshold
    )
        public
        view
        returns (uint64 feeInGwei_)
    {
        require(_feeDoubleThreshold > 0, InvalidFeeDoubleThreshold());

        (uint48 head, uint48 tail) = ($.head, $.tail);
        uint256 numPending = uint256(tail - head);

        // Linear scaling formula: fee = baseFee × (threshold + numPending) / threshold
        // This is mathematically equivalent to: fee = baseFee × (1 + numPending / threshold)
        // but avoids floating point arithmetic
        uint256 multipliedFee = _baseFeeInGwei * (_feeDoubleThreshold + numPending);
        feeInGwei_ = uint64((multipliedFee / _feeDoubleThreshold).min(type(uint64).max));
    }

    /// @notice Returns forced inclusions stored starting from a given index.
    /// @dev Returns an empty array if `_start` is outside the valid range [head, tail) or if
    ///      `_maxCount` is zero. Otherwise returns actual stored entries from the queue.
    /// @param _start The queue index to start reading from (must be in range [head, tail)).
    /// @param _maxCount Maximum number of inclusions to return. Passing zero returns an empty
    ///        array.
    /// @return inclusions_ Forced inclusions from the queue starting at `_start`. The actual length
    ///         will be `min(_maxCount, tail - _start)`, or zero if `_start` is out of range.
    function getForcedInclusions(
        Storage storage $,
        uint48 _start,
        uint48 _maxCount
    )
        internal
        view
        returns (IForcedInclusionStore.ForcedInclusion[] memory inclusions_)
    {
        unchecked {
            (uint48 head, uint48 tail) = ($.head, $.tail);

            if (_start < head || _start >= tail || _maxCount == 0) {
                return new IForcedInclusionStore.ForcedInclusion[](0);
            }

            uint256 count = uint256(tail - _start).min(_maxCount);

            inclusions_ = new IForcedInclusionStore.ForcedInclusion[](count);

            for (uint256 i; i < count; ++i) {
                inclusions_[i] = $.queue[i + _start];
            }
        }
    }

    /// @dev Returns the queue pointers for the forced inclusion storage.
    /// @param $ Storage instance tracking the forced inclusion queue.
    /// @return head_ Index of the next forced inclusion to dequeue.
    /// @return tail_ Index where the next forced inclusion will be enqueued.
    function getForcedInclusionState(Storage storage $)
        internal
        view
        returns (uint48 head_, uint48 tail_)
    {
        (head_, tail_) = ($.head, $.tail);
    }

    // ---------------------------------------------------------------
    // Internal functions
    // ---------------------------------------------------------------

    /// @dev Checks if the oldest remaining forced inclusion is due
    /// @param $ Storage reference
    /// @param _head Current queue head position
    /// @param _tail Current queue tail position
    /// @param _forcedInclusionDelay Delay in seconds before inclusion is due
    /// @return True if the oldest remaining inclusion is due for processing
    function isOldestForcedInclusionDue(
        Storage storage $,
        uint48 _head,
        uint48 _tail,
        uint16 _forcedInclusionDelay
    )
        internal
        view
        returns (bool)
    {
        unchecked {
            if (_head == _tail) return false;

            uint256 timestamp = $.queue[_head].blobSlice.timestamp;
            if (timestamp == 0) return false;

            return block.timestamp >= timestamp + _forcedInclusionDelay;
        }
    }

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

    error InsufficientFee();
    error InvalidFeeDoubleThreshold();
    error OnlySingleBlobAllowed();
}
        

contracts/layer1/core/iface/IForcedInclusionStore.sol

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

import { LibBlobs } from "../libs/LibBlobs.sol";

/// @title IForcedInclusionStore
/// @custom:security-contact security@taiko.xyz
interface IForcedInclusionStore {
    /// @notice Represents a forced inclusion that will be stored onchain.
    struct ForcedInclusion {
        /// @notice The fee in Gwei that was paid to submit the forced inclusion.
        uint64 feeInGwei;
        /// @notice The proposal's blob slice.
        LibBlobs.BlobSlice blobSlice;
    }

    /// @dev Event emitted when a forced inclusion is stored.
    event ForcedInclusionSaved(ForcedInclusion forcedInclusion);

    /// @notice Saves a forced inclusion request
    /// A priority fee must be paid to the contract
    /// @dev Only one blob reference can be saved per forced inclusion
    /// @param _blobReference The blob locator that contains the transaction data
    function saveForcedInclusion(LibBlobs.BlobReference memory _blobReference) external payable;

    /// @notice Returns the current dynamic forced inclusion fee based on queue size
    /// The fee scales linearly with queue size using the formula:
    /// fee = baseFee × (1 + numPending / threshold)
    /// Examples with threshold = 100 and baseFee = 0.01 ETH:
    /// - 0 pending:   fee = 0.01 × (1 + 0/100)   = 0.01 ETH (1× base)
    /// - 50 pending:  fee = 0.01 × (1 + 50/100)  = 0.015 ETH (1.5× base)
    /// - 100 pending: fee = 0.01 × (1 + 100/100) = 0.02 ETH (2× base, DOUBLED)
    /// - 150 pending: fee = 0.01 × (1 + 150/100) = 0.025 ETH (2.5× base)
    /// - 200 pending: fee = 0.01 × (1 + 200/100) = 0.03 ETH (3× base, TRIPLED)
    /// @return feeInGwei_ The current fee in Gwei
    function getCurrentForcedInclusionFee() external view returns (uint64 feeInGwei_);

    /// @notice Returns forced inclusions stored starting from a given index.
    /// @dev Returns an empty array if `_start` is outside the valid range [head, tail) or if
    ///      `_maxCount` is zero. Otherwise returns actual stored entries from the queue.
    /// @param _start The queue index to start reading from (must be in range [head, tail)).
    /// @param _maxCount Maximum number of inclusions to return. Passing zero returns an empty
    ///        array.
    /// @return inclusions_ Forced inclusions from the queue starting at `_start`. The actual length
    ///         will be `min(_maxCount, tail - _start)`, or zero if `_start` is out of range.
    function getForcedInclusions(
        uint48 _start,
        uint48 _maxCount
    )
        external
        view
        returns (ForcedInclusion[] memory inclusions_);

    /// @notice Returns the queue pointers for the forced inclusion store.
    /// @return head_ Index of the oldest forced inclusion in the queue.
    /// @return tail_ Index of the next free slot in the queue.
    function getForcedInclusionState() external view returns (uint48 head_, uint48 tail_);
}
          

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/shared/libs/LibMath.sol

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

/// @title LibMath
/// @dev This library offers additional math functions for uint256.
/// @custom:security-contact security@taiko.xyz
library LibMath {
    /// @dev Returns the smaller of the two given values.
    /// @param _a The first number to compare.
    /// @param _b The second number to compare.
    /// @return The smaller of the two numbers.
    function min(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return _a > _b ? _b : _a;
    }

    /// @dev Returns the larger of the two given values.
    /// @param _a The first number to compare.
    /// @param _b The second number to compare.
    /// @return The larger of the two numbers.
    function max(uint256 _a, uint256 _b) internal pure returns (uint256) {
        return _a > _b ? _a : _b;
    }

    function capToUint64(uint256 _value) internal pure returns (uint64) {
        return uint64(min(_value, type(uint64).max));
    }
}
          

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":"BlobNotFound","inputs":[]},{"type":"error","name":"InsufficientFee","inputs":[]},{"type":"error","name":"InvalidFeeDoubleThreshold","inputs":[]},{"type":"error","name":"NoBlobs","inputs":[]},{"type":"error","name":"OnlySingleBlobAllowed","inputs":[]},{"type":"event","name":"ForcedInclusionSaved","inputs":[{"type":"tuple","name":"forcedInclusion","internalType":"struct IForcedInclusionStore.ForcedInclusion","indexed":false,"components":[{"type":"uint64","name":"feeInGwei","internalType":"uint64"},{"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"}]}]}],"anonymous":false}]
              

Contract Creation Code

Verify & Publish
0x60808060405234601b576105dc90816100208239308160320152f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806343c3d7191461043f5763959554881461002f575f80fd5b307f00000000000000000000000000000000000000000000000000000000000000001461043b5760c036600319011261043b5760043561006d61047a565b610075610490565b91606036606319011261043b5761008a6104a6565b9060643561ffff8116810361043b5782526084359361ffff8516850361043b576020830194855260a4359362ffffff8516850361043b57604084019485525f60406100d36104a6565b60608152826020820152015261ffff8651161561042c5761ffff865116946100fa86610567565b6040519690601f01601f191687016001600160401b038111888210176103e75760405280875261012c601f1991610567565b013660208801375f5b61ffff885116811015610184576101518161ffff8851166104c5565b4961015c828961057e565b52610167818861057e565b511561017557600101610135565b637bb2fa2f60e11b5f5260045ffd5b505162ffffff1693506001856101986104a6565b95818752602087015265ffffffffffff42166040870152510361041d576001600160401b03916101c891846104d2565b1691633b9aca008302916001600160401b0383169283036103fb5782341061040f5760405193604085018581106001600160401b038211176103e7576040528452602084019182526001810180549065ffffffffffff8260301c169165ffffffffffff83146103fb576bffffffffffff0000000000006001840160301b16906bffffffffffff00000000000019161790555f5260205260405f206001600160401b038451166001600160401b031982541617815560018101908251918251908151916001600160401b0383116103e7576801000000000000000083116103e75781548383558084106103c1575b50602001905f5260205f205f5b8381106103ad57505050506002019062ffffff60208201511668ffffffffffff0000006040845493015160181b169168ffffffffffffffffff1916171790556001600160401b036040519360208552511660208401525160408084015260c08301908051916060808601528251809152602060e086019301905f5b8181106103975760208481015162ffffff166080890152604085015165ffffffffffff1660a0890152867f18c4fc1e6ac628dbb537b0375bf0efabf1ff2528af1ec22faa74d2da95c294718988038aa16040519034038152f35b825185526020948501949092019160010161033d565b6001906020845194019381840155016102c2565b825f528360205f2091820191015b8181106103dc57506102b5565b5f81556001016103cf565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b62976f7560e21b5f5260045ffd5b6387a68e9d60e01b5f5260045ffd5b63fdac229f60e01b5f5260045ffd5b5f80fd5b606036600319011261043b57602061046961045861047a565b610460610490565b906004356104d2565b6001600160401b0360405191168152f35b602435906001600160401b038216820361043b57565b604435906001600160401b038216820361043b57565b60405190606082018281106001600160401b038211176103e757604052565b919082018092116103fb57565b916001600160401b0316918215610558576001015465ffffffffffff8082169160301c160365ffffffffffff81116103fb5761051e65ffffffffffff6001600160401b039216846104c5565b91168181029181830414901517156103fb57046001600160401b0381111561054c57506001600160401b0390565b6001600160401b031690565b630ef1aed760e31b5f5260045ffd5b6001600160401b0381116103e75760051b60200190565b80518210156105925760209160051b010190565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220ab057f956a81c6714f99b74ebdfcaa93619ab61759704e64fecc62fd052941ee64736f6c634300081e0033

Deployed ByteCode

0x60806040526004361015610011575f80fd5b5f3560e01c806343c3d7191461043f5763959554881461002f575f80fd5b307f000000000000000000000000d1a27f331c17ed8cbb6dabce67a42d6b8a6b0e141461043b5760c036600319011261043b5760043561006d61047a565b610075610490565b91606036606319011261043b5761008a6104a6565b9060643561ffff8116810361043b5782526084359361ffff8516850361043b576020830194855260a4359362ffffff8516850361043b57604084019485525f60406100d36104a6565b60608152826020820152015261ffff8651161561042c5761ffff865116946100fa86610567565b6040519690601f01601f191687016001600160401b038111888210176103e75760405280875261012c601f1991610567565b013660208801375f5b61ffff885116811015610184576101518161ffff8851166104c5565b4961015c828961057e565b52610167818861057e565b511561017557600101610135565b637bb2fa2f60e11b5f5260045ffd5b505162ffffff1693506001856101986104a6565b95818752602087015265ffffffffffff42166040870152510361041d576001600160401b03916101c891846104d2565b1691633b9aca008302916001600160401b0383169283036103fb5782341061040f5760405193604085018581106001600160401b038211176103e7576040528452602084019182526001810180549065ffffffffffff8260301c169165ffffffffffff83146103fb576bffffffffffff0000000000006001840160301b16906bffffffffffff00000000000019161790555f5260205260405f206001600160401b038451166001600160401b031982541617815560018101908251918251908151916001600160401b0383116103e7576801000000000000000083116103e75781548383558084106103c1575b50602001905f5260205f205f5b8381106103ad57505050506002019062ffffff60208201511668ffffffffffff0000006040845493015160181b169168ffffffffffffffffff1916171790556001600160401b036040519360208552511660208401525160408084015260c08301908051916060808601528251809152602060e086019301905f5b8181106103975760208481015162ffffff166080890152604085015165ffffffffffff1660a0890152867f18c4fc1e6ac628dbb537b0375bf0efabf1ff2528af1ec22faa74d2da95c294718988038aa16040519034038152f35b825185526020948501949092019160010161033d565b6001906020845194019381840155016102c2565b825f528360205f2091820191015b8181106103dc57506102b5565b5f81556001016103cf565b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b62976f7560e21b5f5260045ffd5b6387a68e9d60e01b5f5260045ffd5b63fdac229f60e01b5f5260045ffd5b5f80fd5b606036600319011261043b57602061046961045861047a565b610460610490565b906004356104d2565b6001600160401b0360405191168152f35b602435906001600160401b038216820361043b57565b604435906001600160401b038216820361043b57565b60405190606082018281106001600160401b038211176103e757604052565b919082018092116103fb57565b916001600160401b0316918215610558576001015465ffffffffffff8082169160301c160365ffffffffffff81116103fb5761051e65ffffffffffff6001600160401b039216846104c5565b91168181029181830414901517156103fb57046001600160401b0381111561054c57506001600160401b0390565b6001600160401b031690565b630ef1aed760e31b5f5260045ffd5b6001600160401b0381116103e75760051b60200190565b80518210156105925760209160051b010190565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220ab057f956a81c6714f99b74ebdfcaa93619ab61759704e64fecc62fd052941ee64736f6c634300081e0033

External libraries