Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- DevnetInbox
- Optimization enabled
- true
- Compiler version
- v0.8.30+commit.73712a01
- Optimization runs
- 200
- EVM Version
- prague
- Verified at
- 2025-12-15T12:51:42.141259Z
Constructor Arguments
0x0000000000000000000000009d1313add47c8b69882d6a4605df112fc501f341000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e0000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb3254426400000000000000000000000000acc4d239aa05c797e038b7701be8be6940143900000000000000000000000012100faa7b157e9947340b44409fc7e27ec0abef
Arg [0] (address) : 0x9d1313add47c8b69882d6a4605df112fc501f341
Arg [1] (address) : 0x638f73a482478130bea16ce151e48aec0ab283e0
Arg [2] (address) : 0xbb128fd4942e8143b8dc10f38ccfeadb32544264
Arg [3] (address) : 0x00acc4d239aa05c797e038b7701be8be69401439
Arg [4] (address) : 0x12100faa7b157e9947340b44409fc7e27ec0abef
contracts/layer1/devnet/DevnetInbox.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { Inbox } from "src/layer1/core/impl/Inbox.sol";
import { LibFasterReentryLock } from "src/layer1/mainnet/LibFasterReentryLock.sol";
import "./DevnetInbox_Layout.sol"; // DO NOT DELETE
/// @title DevnetInbox
/// @dev This contract extends the base Inbox contract for devnet deployment
/// with optimized reentrancy lock implementation.
/// @custom:security-contact security@taiko.xyz
contract DevnetInbox is Inbox {
// ---------------------------------------------------------------
// Constants
// ---------------------------------------------------------------
/// @dev Ring buffer size for storing proposal hashes.
/// Assumptions:
/// - D = 2: Proposals may continue without finalization for up to 2 days.
/// - P = 6: On average, 1 proposal is submitted every 6 Ethereum slots (≈72s).
///
/// Calculation:
/// _RING_BUFFER_SIZE = (86400 * D) / 12 / P
/// = (86400 * 2) / 12 / 6
/// = 2400
uint64 private constant _RING_BUFFER_SIZE = 100;
// ---------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------
constructor(
address _proofVerifier,
address _proposerChecker,
address _proverWhitelist,
address _signalService,
address _codec
)
Inbox(Config({
codec: _codec,
proofVerifier: _proofVerifier,
proposerChecker: _proposerChecker,
proverWhitelist: _proverWhitelist,
signalService: _signalService,
provingWindow: 2 hours,
maxProofSubmissionDelay: 3 minutes, // We want this to be lower than the proposal cadence
ringBufferSize: _RING_BUFFER_SIZE,
basefeeSharingPctg: 75,
minForcedInclusionCount: 1,
forcedInclusionDelay: 0,
forcedInclusionFeeInGwei: 10_000_000, // 0.01 ETH base fee
forcedInclusionFeeDoubleThreshold: 50, // fee doubles at 50 pending
minCheckpointDelay: 384 seconds, // 1 epoch
permissionlessInclusionMultiplier: 5
}))
{ }
// ---------------------------------------------------------------
// Internal Functions
// ---------------------------------------------------------------
function _storeReentryLock(uint8 _reentry) internal override {
LibFasterReentryLock.storeReentryLock(_reentry);
}
function _loadReentryLock() internal view override returns (uint8) {
return LibFasterReentryLock.loadReentryLock();
}
}
contracts/layer1/core/iface/IProverWhitelist.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProverWhitelist
/// @notice Interface for checking if an address is authorized to prove blocks
/// @custom:security-contact security@taiko.xyz
interface IProverWhitelist {
/// @notice Checks if an address is a whitelisted prover
/// @param _prover The address to check
/// @return isWhitelisted_ True if the address is whitelisted, false otherwise
/// @return proverCount_ The total number of whitelisted provers
function isProverWhitelisted(address _prover)
external
view
returns (bool isWhitelisted_, uint256 proverCount_);
}
contracts/shared/common/IResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IResolver
/// @notice This contract acts as a bridge for name-to-address resolution.
/// @custom:security-contact security@taiko.xyz
interface IResolver {
error RESOLVED_TO_ZERO_ADDRESS();
/// @notice Resolves a name to its address deployed on a specified chain.
/// @param _chainId The chainId of interest.
/// @param _name Name whose address is to be resolved.
/// @param _allowZeroAddress If set to true, does not throw if the resolved
/// address is `address(0)`.
/// @return Address associated with the given name on the specified
/// chain.
function resolve(
uint256 _chainId,
bytes32 _name,
bool _allowZeroAddress
)
external
view
returns (address);
}
node_modules/@openzeppelin/contracts/utils/StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}
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/LibProveInputCodec.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IInbox } from "../iface/IInbox.sol";
import { LibPackUnpack as P } from "./LibPackUnpack.sol";
/// @title LibProveInputCodec
/// @notice Compact encoder/decoder for ProveInput using LibPackUnpack.
/// @custom:security-contact security@taiko.xyz
library LibProveInputCodec {
/// @notice Encodes ProveInput data using compact packing.
function encode(IInbox.ProveInput memory _input) internal pure returns (bytes memory encoded_) {
IInbox.Commitment memory c = _input.commitment;
uint256 bufferSize = _calculateSize(c.transitions.length);
encoded_ = new bytes(bufferSize);
uint256 ptr = P.dataPtr(encoded_);
ptr = P.packUint48(ptr, c.firstProposalId);
ptr = P.packBytes32(ptr, c.firstProposalParentBlockHash);
ptr = P.packBytes32(ptr, c.lastProposalHash);
ptr = P.packAddress(ptr, c.actualProver);
ptr = P.packUint48(ptr, c.endBlockNumber);
ptr = P.packBytes32(ptr, c.endStateRoot);
P.checkArrayLength(c.transitions.length);
ptr = P.packUint16(ptr, uint16(c.transitions.length));
for (uint256 i; i < c.transitions.length; ++i) {
_encodeTransition(ptr, c.transitions[i]);
ptr += 78; // Transition size: 20 + 20 + 6 + 32 = 78 bytes
}
// Encode forceCheckpointSync
P.packUint8(ptr, _input.forceCheckpointSync ? 1 : 0);
}
/// @notice Decodes ProveInput data using compact packing.
function decode(bytes memory _data) internal pure returns (IInbox.ProveInput memory input_) {
uint256 ptr = P.dataPtr(_data);
(input_.commitment.firstProposalId, ptr) = P.unpackUint48(ptr);
(input_.commitment.firstProposalParentBlockHash, ptr) = P.unpackBytes32(ptr);
(input_.commitment.lastProposalHash, ptr) = P.unpackBytes32(ptr);
(input_.commitment.actualProver, ptr) = P.unpackAddress(ptr);
(input_.commitment.endBlockNumber, ptr) = P.unpackUint48(ptr);
(input_.commitment.endStateRoot, ptr) = P.unpackBytes32(ptr);
uint16 transitionsLength;
(transitionsLength, ptr) = P.unpackUint16(ptr);
input_.commitment.transitions = new IInbox.Transition[](transitionsLength);
for (uint256 i; i < transitionsLength; ++i) {
(input_.commitment.transitions[i], ptr) = _decodeTransition(ptr);
}
// Decode forceCheckpointSync
uint8 forceCheckpointSyncByte;
(forceCheckpointSyncByte,) = P.unpackUint8(ptr);
input_.forceCheckpointSync = forceCheckpointSyncByte != 0;
}
/// @dev Calculate the size needed for encoding.
/// @param _numTransitions Number of transitions in the array.
/// @return size_ Total byte size needed.
function _calculateSize(uint256 _numTransitions) private pure returns (uint256 size_) {
unchecked {
// Fixed fields:
// firstProposalId: 6 bytes
// firstProposalParentBlockHash: 32 bytes
// lastProposalHash: 32 bytes
// actualProver: 20 bytes
// endBlockNumber: 6 bytes
// endStateRoot: 32 bytes
// transitions array length: 2 bytes
// forceCheckpointSync: 1 byte
// Total fixed: 131 bytes
//
// Per Transition:
// proposer: 20 bytes
// designatedProver: 20 bytes
// timestamp: 6 bytes
// blockHash: 32 bytes
// Total per transition: 78 bytes
size_ = 131 + (_numTransitions * 78);
}
}
function _encodeTransition(
uint256 _ptr,
IInbox.Transition memory _transition
)
private
pure
returns (uint256 newPtr_)
{
newPtr_ = P.packAddress(_ptr, _transition.proposer);
newPtr_ = P.packAddress(newPtr_, _transition.designatedProver);
newPtr_ = P.packUint48(newPtr_, _transition.timestamp);
newPtr_ = P.packBytes32(newPtr_, _transition.blockHash);
}
function _decodeTransition(uint256 _ptr)
private
pure
returns (IInbox.Transition memory transition_, uint256 newPtr_)
{
(transition_.proposer, newPtr_) = P.unpackAddress(_ptr);
(transition_.designatedProver, newPtr_) = P.unpackAddress(newPtr_);
(transition_.timestamp, newPtr_) = P.unpackUint48(newPtr_);
(transition_.blockHash, newPtr_) = P.unpackBytes32(newPtr_);
}
}
node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
contracts/layer1/verifiers/IProofVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProofVerifier
/// @notice Interface for verifying validity proofs for state transitions
/// @custom:security-contact security@taiko.xyz
interface IProofVerifier {
/// @notice Verifies a validity proof for a state transition
/// @dev This function must revert if the proof is invalid
/// @param _proposalAge The age in seconds of the proposal being proven. Only set for
/// single-proposal proofs (calculated as block.timestamp - proposal.timestamp).
/// For multi-proposal batches, this is always 0, meaning "not applicable".
/// Verifiers should interpret _proposalAge == 0 as "not applicable" rather than
/// "instant proof". This parameter enables age-based verification logic, such as
/// detecting and handling prover-killer proposals differently.
/// @param _commitmentHash Hash of the last proposal hash and commitment data
/// @param _proof The proof data
function verifyProof(
uint256 _proposalAge,
bytes32 _commitmentHash,
bytes calldata _proof
)
external
view;
}
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/signal/ISignalService.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "./ICheckpointStore.sol";
/// @title ISignalService
/// @notice The SignalService contract serves as a secure cross-chain message
/// passing system. It defines methods for sending and verifying signals with
/// merkle proofs. The trust assumption is that the target chain has secure
/// access to the merkle root (such as Taiko injects it in the anchor
/// transaction). With this, verifying a signal is reduced to simply verifying
/// a merkle proof.
/// @custom:security-contact security@taiko.xyz
interface ISignalService is ICheckpointStore {
/// @dev DEPRECATED
/// @dev Caching is no longer supported
enum CacheOption {
CACHE_NOTHING,
CACHE_SIGNAL_ROOT,
CACHE_STATE_ROOT,
CACHE_BOTH
}
struct HopProof {
/// @notice This hop's destination chain ID. If there is a next hop, this ID is the next
/// hop's source chain ID.
uint64 chainId;
/// @notice The ID of a source chain block whose state root has been synced to the hop's
/// destination chain.
/// Note that this block ID must be greater than or equal to the block ID where the signal
/// was sent on the source chain.
uint64 blockId;
/// @notice The state root or signal root of the source chain at the above blockId. This
/// value has been synced to the destination chain.
/// @dev To get both the blockId and the rootHash, apps should subscribe to the
/// ChainDataSynced event or query `topBlockId` first using the source chain's ID and
/// LibStrings.H_STATE_ROOT to get the most recent block ID synced, then call
/// `getSyncedChainData` to read the synchronized data.
bytes32 rootHash;
/// @notice Options to cache either the state roots or signal roots of middle-hops to the
/// current chain.
/// @dev DEPRECATED - this value will be ignored
CacheOption cacheOption;
/// @notice The signal service's account proof. If this value is empty, then `rootHash` will
/// be used as the signal root, otherwise, `rootHash` will be used as the state root.
bytes[] accountProof;
/// @notice The signal service's storage proof.
bytes[] storageProof;
}
/// @notice Emitted when a signal is sent.
/// @param app The address that initiated the signal.
/// @param signal The signal (message) that was sent.
/// @param slot The location in storage where this signal is stored.
/// @param value The value of the signal.
event SignalSent(address app, bytes32 signal, bytes32 slot, bytes32 value);
/// @notice Send a signal (message) by setting the storage slot to the same value as the signal
/// itself.
/// @param _signal The signal (message) to send.
/// @return slot_ The location in storage where this signal is stored.
function sendSignal(bytes32 _signal) external returns (bytes32 slot_);
/// @notice Checks whether a signal has been received on the target chain and caches the result if successful.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain. If this proof is empty, then we check if this signal has been marked as
/// received by TaikoL2.
/// @return numCacheOps_ The number of newly cached items.
function proveSignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
returns (uint256 numCacheOps_);
/// @notice Verifies if a signal has been received on the target chain.
/// This is the "readonly" version of proveSignalReceived.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain. If this proof is empty, then we check if this signal has been marked as
/// received by TaikoL2.
function verifySignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
view;
/// @notice Verifies if a particular signal has already been sent.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) that was sent.
/// @return true if the signal has been sent, otherwise false.
function isSignalSent(address _app, bytes32 _signal) external view returns (bool);
/// @notice Verifies if a particular signal has already been sent.
/// @param _signalSlot The location in storage where this signal is stored.
function isSignalSent(bytes32 _signalSlot) external view returns (bool);
}
contracts/layer1/core/iface/IProposerChecker.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProposerChecker
/// @notice Interface for checking if an address is authorized to propose blocks
/// @custom:security-contact security@taiko.xyz
interface IProposerChecker {
error InvalidProposer();
/// @notice Checks if an address is a valid proposer
/// @param _proposer The address to check
/// @param _lookaheadData Encoded lookahead metadata used by preconf-aware proposer checkers.
/// @return endOfSubmissionWindowTimestamp_ The timestamp of the last slot where the current
/// preconfer can propose.
/// @dev This function must revert if the address is not a valid proposer
function checkProposer(
address _proposer,
bytes calldata _lookaheadData
)
external
returns (uint48 endOfSubmissionWindowTimestamp_);
}
contracts/layer1/core/libs/LibProvedEventCodec.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IInbox } from "../iface/IInbox.sol";
import { LibPackUnpack as P } from "./LibPackUnpack.sol";
/// @title LibProvedEventCodec
/// @notice Compact encoder/decoder for ProvedEventPayload using LibPackUnpack.
/// @custom:security-contact security@taiko.xyz
library LibProvedEventCodec {
/// @notice Encodes a ProvedEventPayload into bytes using compact encoding.
function encode(IInbox.ProvedEventPayload memory _payload)
internal
pure
returns (bytes memory encoded_)
{
IInbox.Commitment memory c = _payload.input.commitment;
uint256 bufferSize = _calculateSize(c.transitions.length);
encoded_ = new bytes(bufferSize);
uint256 ptr = P.dataPtr(encoded_);
// Encode Commitment
ptr = P.packUint48(ptr, c.firstProposalId);
ptr = P.packBytes32(ptr, c.firstProposalParentBlockHash);
ptr = P.packBytes32(ptr, c.lastProposalHash);
ptr = P.packAddress(ptr, c.actualProver);
ptr = P.packUint48(ptr, c.endBlockNumber);
ptr = P.packBytes32(ptr, c.endStateRoot);
P.checkArrayLength(c.transitions.length);
ptr = P.packUint16(ptr, uint16(c.transitions.length));
for (uint256 i; i < c.transitions.length; ++i) {
ptr = _encodeTransition(ptr, c.transitions[i]);
}
// Encode forceCheckpointSync
P.packUint8(ptr, _payload.input.forceCheckpointSync ? 1 : 0);
}
/// @notice Decodes bytes into a ProvedEventPayload using compact encoding.
function decode(bytes memory _data)
internal
pure
returns (IInbox.ProvedEventPayload memory payload_)
{
uint256 ptr = P.dataPtr(_data);
// Decode Commitment
(payload_.input.commitment.firstProposalId, ptr) = P.unpackUint48(ptr);
(payload_.input.commitment.firstProposalParentBlockHash, ptr) = P.unpackBytes32(ptr);
(payload_.input.commitment.lastProposalHash, ptr) = P.unpackBytes32(ptr);
(payload_.input.commitment.actualProver, ptr) = P.unpackAddress(ptr);
(payload_.input.commitment.endBlockNumber, ptr) = P.unpackUint48(ptr);
(payload_.input.commitment.endStateRoot, ptr) = P.unpackBytes32(ptr);
uint16 transitionsLength;
(transitionsLength, ptr) = P.unpackUint16(ptr);
payload_.input.commitment.transitions = new IInbox.Transition[](transitionsLength);
for (uint256 i; i < transitionsLength; ++i) {
(payload_.input.commitment.transitions[i], ptr) = _decodeTransition(ptr);
}
// Decode forceCheckpointSync
uint8 forceCheckpointSyncByte;
(forceCheckpointSyncByte,) = P.unpackUint8(ptr);
payload_.input.forceCheckpointSync = forceCheckpointSyncByte != 0;
}
/// @dev Calculate the exact byte size needed for encoding a ProvedEventPayload.
/// @param _numTransitions Number of transitions in the input.
/// @return size_ Total byte size needed.
function _calculateSize(uint256 _numTransitions) private pure returns (uint256 size_) {
unchecked {
// ProveInput fixed fields:
// firstProposalId: 6 bytes
// firstProposalParentBlockHash: 32 bytes
// lastProposalHash: 32 bytes
// actualProver: 20 bytes
// endBlockNumber: 6 bytes
// endStateRoot: 32 bytes
// transitions array length: 2 bytes
// forceCheckpointSync: 1 byte
// Total ProveInput fixed: 131 bytes
//
// Per Transition:
// proposer: 20 bytes
// designatedProver: 20 bytes
// timestamp: 6 bytes
// blockHash: 32 bytes
// Total per transition: 78 bytes
//
// Total = 131 + (numTransitions * 78)
size_ = 131 + (_numTransitions * 78);
}
}
function _encodeTransition(
uint256 _ptr,
IInbox.Transition memory _transition
)
private
pure
returns (uint256 newPtr_)
{
newPtr_ = P.packAddress(_ptr, _transition.proposer);
newPtr_ = P.packAddress(newPtr_, _transition.designatedProver);
newPtr_ = P.packUint48(newPtr_, _transition.timestamp);
newPtr_ = P.packBytes32(newPtr_, _transition.blockHash);
}
function _decodeTransition(uint256 _ptr)
private
pure
returns (IInbox.Transition memory transition_, uint256 newPtr_)
{
(transition_.proposer, newPtr_) = P.unpackAddress(_ptr);
(transition_.designatedProver, newPtr_) = P.unpackAddress(newPtr_);
(transition_.timestamp, newPtr_) = P.unpackUint48(newPtr_);
(transition_.blockHash, newPtr_) = P.unpackBytes32(newPtr_);
}
}
node_modules/@openzeppelin/contracts/proxy/beacon/IBeacon.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
contracts/layer1/devnet/DevnetInbox_Layout.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title DevnetInboxLayout
/// @notice Storage layout documentation for DevnetInbox
/// @dev This file is auto-generated by gen-layouts.sh. DO NOT EDIT MANUALLY.
/// @custom:security-contact security@taiko.xyz
// solhint-disable max-line-length
// _initialized | uint8 | Slot: 0 | Offset: 0 | Bytes: 1
// _initializing | bool | Slot: 0 | Offset: 1 | Bytes: 1
// __gap | uint256[50] | Slot: 1 | Offset: 0 | Bytes: 1600
// _owner | address | Slot: 51 | Offset: 0 | Bytes: 20
// __gap | uint256[49] | Slot: 52 | Offset: 0 | Bytes: 1568
// _pendingOwner | address | Slot: 101 | Offset: 0 | Bytes: 20
// __gap | uint256[49] | Slot: 102 | Offset: 0 | Bytes: 1568
// __gapFromOldAddressResolver | uint256[50] | Slot: 151 | Offset: 0 | Bytes: 1600
// __reentry | uint8 | Slot: 201 | Offset: 0 | Bytes: 1
// __paused | uint8 | Slot: 201 | Offset: 1 | Bytes: 1
// __gap | uint256[49] | Slot: 202 | Offset: 0 | Bytes: 1568
// activationTimestamp | uint48 | Slot: 251 | Offset: 0 | Bytes: 6
// _coreState | struct IInbox.CoreState | Slot: 252 | Offset: 0 | Bytes: 64
// _proposalHashes | mapping(uint256 => bytes32) | Slot: 254 | Offset: 0 | Bytes: 32
// _forcedInclusionStorage | struct LibForcedInclusion.Storage | Slot: 255 | Offset: 0 | Bytes: 64
// __gap | uint256[44] | Slot: 257 | Offset: 0 | Bytes: 1408
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/layer1/mainnet/LibFasterReentryLock.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title LibFasterReentryLock
/// @custom:security-contact security@taiko.xyz
library LibFasterReentryLock {
/// @dev The slot in transient storage of the reentry lock.
/// This is the result of keccak256("ownerUUPS.reentry_slot") plus 1. The addition aims to
/// prevent hash collisions with slots defined in EIP-1967, where slots are derived by
/// keccak256("something") - 1, and with slots in SignalService, calculated directly with
/// keccak256("something").
bytes32 private constant _REENTRY_SLOT =
0xa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b;
function storeReentryLock(uint8 _reentry) internal {
assembly {
tstore(_REENTRY_SLOT, _reentry)
}
}
function loadReentryLock() internal view returns (uint8 reentry_) {
assembly {
reentry_ := tload(_REENTRY_SLOT)
}
}
}
node_modules/@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
node_modules/@openzeppelin/contracts/interfaces/draft-IERC1822.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
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_);
}
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() }
}
}
}
contracts/layer1/core/impl/Inbox.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IForcedInclusionStore } from "../iface/IForcedInclusionStore.sol";
import { IInbox } from "../iface/IInbox.sol";
import { IProposerChecker } from "../iface/IProposerChecker.sol";
import { IProverWhitelist } from "../iface/IProverWhitelist.sol";
import { LibBlobs } from "../libs/LibBlobs.sol";
import { LibForcedInclusion } from "../libs/LibForcedInclusion.sol";
import { LibHashOptimized } from "../libs/LibHashOptimized.sol";
import { LibInboxSetup } from "../libs/LibInboxSetup.sol";
import { LibProposeInputCodec } from "../libs/LibProposeInputCodec.sol";
import { LibProposedEventCodec } from "../libs/LibProposedEventCodec.sol";
import { LibProveInputCodec } from "../libs/LibProveInputCodec.sol";
import { LibProvedEventCodec } from "../libs/LibProvedEventCodec.sol";
import { IProofVerifier } from "src/layer1/verifiers/IProofVerifier.sol";
import { EssentialContract } from "src/shared/common/EssentialContract.sol";
import { LibAddress } from "src/shared/libs/LibAddress.sol";
import { LibBonds } from "src/shared/libs/LibBonds.sol";
import { LibMath } from "src/shared/libs/LibMath.sol";
import { ICheckpointStore } from "src/shared/signal/ICheckpointStore.sol";
import { ISignalService } from "src/shared/signal/ISignalService.sol";
/// @title Inbox
/// @notice Core contract for managing L2 proposals, proof verification, and forced inclusion in
/// Taiko's based rollup architecture.
/// @dev The Pacaya inbox contract is not being upgraded to the Shasta implementation;
/// instead, Shasta uses a separate inbox address.
/// @dev This contract implements the fundamental inbox logic including:
/// - Proposal submission with forced inclusion support
/// - Sequential proof verification
/// - Ring buffer storage for efficient state management
/// - Bond instruction calculation(but actual funds are managed on L2)
/// - Finalization of proven proposals with checkpoint rate limiting
/// @custom:security-contact security@taiko.xyz
contract Inbox is IInbox, IForcedInclusionStore, EssentialContract {
using LibAddress for address;
using LibMath for uint48;
using LibMath for uint256;
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @notice Result from consuming forced inclusions
struct ConsumptionResult {
DerivationSource[] sources;
bool allowsPermissionless;
}
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
event InboxActivated(bytes32 lastPacayaBlockHash);
// ---------------------------------------------------------------
// Immutable Variables
// ---------------------------------------------------------------
/// @notice The codec used for encoding and hashing.
address internal immutable _codec;
/// @notice The proof verifier contract.
IProofVerifier internal immutable _proofVerifier;
/// @notice The proposer checker contract.
IProposerChecker internal immutable _proposerChecker;
/// @notice The prover whitelist contract (address(0) means no whitelist)
IProverWhitelist internal immutable _proverWhitelist;
/// @notice Signal service responsible for checkpoints and bond signals.
ISignalService internal immutable _signalService;
/// @notice The proving window in seconds.
uint48 internal immutable _provingWindow;
/// @notice Maximum delay allowed between sequential proofs to remain on time.
uint48 internal immutable _maxProofSubmissionDelay;
/// @notice The ring buffer size for storing proposal hashes.
uint256 internal immutable _ringBufferSize;
/// @notice The percentage of basefee paid to coinbase.
uint8 internal immutable _basefeeSharingPctg;
/// @notice The minimum number of forced inclusions that the proposer is forced to process if
/// they are due.
uint256 internal immutable _minForcedInclusionCount;
/// @notice The delay for forced inclusions measured in seconds.
uint16 internal immutable _forcedInclusionDelay;
/// @notice The base fee for forced inclusions in Gwei.
uint64 internal immutable _forcedInclusionFeeInGwei;
/// @notice Queue size at which the fee doubles. See Config for formula details.
uint64 internal immutable _forcedInclusionFeeDoubleThreshold;
/// @notice The minimum delay between checkpoints in seconds.
uint16 internal immutable _minCheckpointDelay;
/// @notice The multiplier to determine when a forced inclusion is too old so that proposing
/// becomes permissionless
uint8 internal immutable _permissionlessInclusionMultiplier;
// ---------------------------------------------------------------
// State Variables
// ---------------------------------------------------------------
/// @notice The timestamp when the first activation occurred.
uint48 public activationTimestamp;
/// @notice Persisted core state.
CoreState internal _coreState;
/// @dev Ring buffer for storing proposal hashes indexed by buffer slot
/// - bufferSlot: The ring buffer slot calculated as proposalId % ringBufferSize
/// - proposalHash: The keccak256 hash of the Proposal struct
mapping(uint256 bufferSlot => bytes32 proposalHash) internal _proposalHashes;
/// @dev Storage for forced inclusion requests
/// @dev 2 slots used
LibForcedInclusion.Storage private _forcedInclusionStorage;
uint256[44] private __gap;
// ---------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------
/// @notice Initializes the Inbox contract
/// @param _config Configuration struct containing all constructor parameters
constructor(Config memory _config) {
LibInboxSetup.validateConfig(_config);
_codec = _config.codec;
_proofVerifier = IProofVerifier(_config.proofVerifier);
_proposerChecker = IProposerChecker(_config.proposerChecker);
_proverWhitelist = IProverWhitelist(_config.proverWhitelist);
_signalService = ISignalService(_config.signalService);
_provingWindow = _config.provingWindow;
_maxProofSubmissionDelay = _config.maxProofSubmissionDelay;
_ringBufferSize = _config.ringBufferSize;
_basefeeSharingPctg = _config.basefeeSharingPctg;
_minForcedInclusionCount = _config.minForcedInclusionCount;
_forcedInclusionDelay = _config.forcedInclusionDelay;
_forcedInclusionFeeInGwei = _config.forcedInclusionFeeInGwei;
_forcedInclusionFeeDoubleThreshold = _config.forcedInclusionFeeDoubleThreshold;
_minCheckpointDelay = _config.minCheckpointDelay;
_permissionlessInclusionMultiplier = _config.permissionlessInclusionMultiplier;
}
// ---------------------------------------------------------------
// External Functions
// ---------------------------------------------------------------
/// @notice Initializes the owner of the inbox.
/// @param _owner The owner of this contract
function init(address _owner) external initializer {
__Essential_init(_owner);
}
/// @notice Activates the inbox so that it can start accepting proposals.
/// @dev Can be called multiple times within the activation window to handle reorgs.
/// @param _lastPacayaBlockHash The block hash of the last Pacaya block
function activate(bytes32 _lastPacayaBlockHash) external onlyOwner {
(
uint48 newActivationTimestamp,
CoreState memory state,
Derivation memory derivation,
Proposal memory proposal,
bytes32 genesisProposalHash
) = LibInboxSetup.activate(_lastPacayaBlockHash, activationTimestamp);
activationTimestamp = newActivationTimestamp;
_coreState = state;
_setProposalHash(0, genesisProposalHash);
_emitProposedEvent(proposal, derivation);
emit InboxActivated(_lastPacayaBlockHash);
}
/// @inheritdoc IInbox
/// @notice Proposes new L2 blocks and forced inclusions to the rollup using blobs for DA.
/// @dev Key behaviors:
/// 1. Validates proposer authorization via `IProposerChecker`
/// 2. Process `input.numForcedInclusions` forced inclusions. The proposer is forced to
/// process at least `config.minForcedInclusionCount` if they are due.
/// 3. Updates core state and emits `Proposed` event
/// NOTE: This function can only be called once per block to prevent spams that can fill the
/// ring buffer.
function propose(bytes calldata _lookahead, bytes calldata _data) external nonReentrant {
unchecked {
ProposeInput memory input = LibProposeInputCodec.decode(_data);
_validateProposeInput(input);
uint48 nextProposalId = _coreState.nextProposalId;
uint48 lastProposalBlockId = _coreState.lastProposalBlockId;
uint48 lastFinalizedProposalId = _coreState.lastFinalizedProposalId;
require(nextProposalId > 0, ActivationRequired());
(Proposal memory proposal, Derivation memory derivation) = _buildProposal(
input, _lookahead, nextProposalId, lastProposalBlockId, lastFinalizedProposalId
);
_coreState.nextProposalId = nextProposalId + 1;
_coreState.lastProposalBlockId = uint48(block.number);
_setProposalHash(proposal.id, LibHashOptimized.hashProposal(proposal));
_emitProposedEvent(proposal, derivation);
}
}
/// @inheritdoc IInbox
///
/// @dev The proof covers a contiguous range of proposals. The input contains an array of
/// Transition structs, each with the proposal's metadata and checkpoint hash. The proof range
/// can start at or before the last finalized proposal to handle race conditions where
/// proposals get finalized between proof generation and submission.
///
/// Example: Proving proposals 3-7 when lastFinalizedProposalId=4
///
/// lastFinalizedProposalId nextProposalId
/// ┆ ┆
/// ▼ ▼
/// 0 1 2 3 4 5 6 7 8 9
/// ■─────■─────■─────■─────■─────□─────□─────□─────□─────
/// ▲ ▲ ▲
/// ┆<-offset-> ┆ ┆
/// ┆ ┆
/// ┆<- input.transitions[] ->┆
/// firstProposalId lastProposalId
///
/// Key validation rules:
/// 1. firstProposalId <= lastFinalizedProposalId + 1 (can overlap with finalized range)
/// 2. lastProposalId < nextProposalId (cannot prove unproposed blocks)
/// 3. lastProposalId >= lastFinalizedProposalId + 1 (must advance at least one proposal)
/// 4. The block hash must link to the lastFinalizedBlockHash
///
/// @param _data Encoded ProveInput struct
/// @param _proof Validity proof for the batch of proposals
function prove(bytes calldata _data, bytes calldata _proof) external {
unchecked {
bool isWhitelistEnabled = _checkProver(msg.sender);
CoreState memory state = _coreState;
ProveInput memory input = LibProveInputCodec.decode(_data);
// -------------------------------------------------------------------------------
// 1. Validate batch bounds and calculate offset of the first unfinalized proposal
// -------------------------------------------------------------------------------
Commitment memory commitment = input.commitment;
// `offset` is the index of the next-to-finalize proposal in the transitions array.
(uint256 numProposals, uint256 lastProposalId, uint48 offset) =
_validateCommitment(state, commitment);
// ---------------------------------------------------------
// 2. Verify checkpoint hash continuity and last proposal hash
// ---------------------------------------------------------
// The parent block hash must match the stored lastFinalizedBlockHash.
bytes32 expectedParentHash = offset == 0
? commitment.firstProposalParentBlockHash
: commitment.transitions[offset - 1].blockHash;
require(state.lastFinalizedBlockHash == expectedParentHash, ParentBlockHashMismatch());
require(
commitment.lastProposalHash == getProposalHash(lastProposalId),
LastProposalHashMismatch()
);
// ---------------------------------------------------------
// 3. Process bond instruction
// ---------------------------------------------------------
// Bond transfers only apply when whitelist is not enabled.
if (!isWhitelistEnabled) {
_processBondInstruction(commitment, offset);
}
// -----------------------------------------------------------------------------
// 4. Sync checkpoint
// -----------------------------------------------------------------------------
if (
input.forceCheckpointSync
|| block.timestamp >= state.lastCheckpointTimestamp + _minCheckpointDelay
) {
_signalService.saveCheckpoint(
ICheckpointStore.Checkpoint({
blockNumber: commitment.endBlockNumber,
stateRoot: commitment.endStateRoot,
blockHash: commitment.transitions[numProposals - 1].blockHash
})
);
state.lastCheckpointTimestamp = uint48(block.timestamp);
}
// ---------------------------------------------------------
// 5. Update core state and emit event
// ---------------------------------------------------------
state.lastFinalizedProposalId = uint48(lastProposalId);
state.lastFinalizedTimestamp = uint48(block.timestamp);
state.lastFinalizedBlockHash = commitment.transitions[numProposals - 1].blockHash;
_coreState = state;
emit Proved(LibProvedEventCodec.encode(ProvedEventPayload(input)));
// ---------------------------------------------------------
// 6. Verify the proof
// ---------------------------------------------------------
// We count the proposalAge as the time since it became available for proving.
uint256 proposalAge = block.timestamp
- commitment.transitions[offset].timestamp.max(state.lastFinalizedTimestamp);
bytes32 commitmentHash = LibHashOptimized.hashCommitment(commitment);
emit DebugHash(1, commitmentHash);
emit DebugNumber(2, commitment.firstProposalId);
emit DebugHash(3, commitment.firstProposalParentBlockHash);
emit DebugHash(4, commitment.lastProposalHash);
emit DebugAddress(5, commitment.actualProver);
emit DebugNumber(6, commitment.endBlockNumber);
emit DebugHash(7, commitment.endStateRoot);
emit DebugHash(8, commitment.transitions[0].blockHash);
emit DebugAddress(9, commitment.transitions[0].proposer);
emit DebugAddress(10, commitment.transitions[0].designatedProver);
emit DebugNumber(11, commitment.transitions[0].timestamp);
_proofVerifier.verifyProof(
proposalAge, commitmentHash, _proof
);
}
}
/// @inheritdoc IForcedInclusionStore
/// @dev This function will revert if called before the first non-activation proposal is
/// submitted to make sure blocks have been produced already and the derivation can use the
/// parent's block timestamp.
function saveForcedInclusion(LibBlobs.BlobReference memory _blobReference) external payable {
bytes32 proposalHash = _proposalHashes[1];
require(proposalHash != bytes32(0), IncorrectProposalCount());
uint256 refund = LibForcedInclusion.saveForcedInclusion(
_forcedInclusionStorage,
_forcedInclusionFeeInGwei,
_forcedInclusionFeeDoubleThreshold,
_blobReference
);
// Refund excess payment to the sender
if (refund > 0) {
msg.sender.sendEtherAndVerify(refund);
}
}
// ---------------------------------------------------------------
// External and Public View Functions
// ---------------------------------------------------------------
/// @inheritdoc IForcedInclusionStore
function getCurrentForcedInclusionFee() external view returns (uint64 feeInGwei_) {
return LibForcedInclusion.getCurrentForcedInclusionFee(
_forcedInclusionStorage, _forcedInclusionFeeInGwei, _forcedInclusionFeeDoubleThreshold
);
}
/// @inheritdoc IForcedInclusionStore
function getForcedInclusions(
uint48 _start,
uint48 _maxCount
)
external
view
returns (IForcedInclusionStore.ForcedInclusion[] memory inclusions_)
{
return LibForcedInclusion.getForcedInclusions(_forcedInclusionStorage, _start, _maxCount);
}
/// @inheritdoc IForcedInclusionStore
function getForcedInclusionState() external view returns (uint48 head_, uint48 tail_) {
return LibForcedInclusion.getForcedInclusionState(_forcedInclusionStorage);
}
/// @inheritdoc IInbox
function getConfig() external view returns (Config memory config_) {
config_ = Config({
codec: _codec,
proofVerifier: address(_proofVerifier),
proposerChecker: address(_proposerChecker),
proverWhitelist: address(_proverWhitelist),
signalService: address(_signalService),
provingWindow: _provingWindow,
maxProofSubmissionDelay: _maxProofSubmissionDelay,
ringBufferSize: _ringBufferSize,
basefeeSharingPctg: _basefeeSharingPctg,
minForcedInclusionCount: _minForcedInclusionCount,
forcedInclusionDelay: _forcedInclusionDelay,
forcedInclusionFeeInGwei: _forcedInclusionFeeInGwei,
forcedInclusionFeeDoubleThreshold: _forcedInclusionFeeDoubleThreshold,
minCheckpointDelay: _minCheckpointDelay,
permissionlessInclusionMultiplier: _permissionlessInclusionMultiplier
});
}
/// @inheritdoc IInbox
function getCoreState() external view returns (CoreState memory) {
return _coreState;
}
/// @inheritdoc IInbox
/// @dev Note that due to the ring buffer nature of the `_proposalHashes` mapping proposals
/// may have been overwritten by a new one. You should verify that the hash matches the
/// expected proposal.
function getProposalHash(uint256 _proposalId) public view returns (bytes32) {
return _proposalHashes[_proposalId % _ringBufferSize];
}
// ---------------------------------------------------------------
// Private State-Changing Functions
// ---------------------------------------------------------------
/// @dev Builds proposal and derivation data. It also checks if `msg.sender` can propose.
/// @param _input The propose input data.
/// @param _lookahead Encoded data forwarded to the proposer checker (i.e. lookahead payloads).
/// @param _nextProposalId The proposal ID to assign.
/// @param _lastProposalBlockId The last block number where a proposal was made.
/// @param _lastFinalizedProposalId The ID of the last finalized proposal.
/// @return proposal_ The proposal with final endOfSubmissionWindowTimestamp and derivation
/// hash set.
/// @return derivation_ The derivation data for the proposal.
function _buildProposal(
ProposeInput memory _input,
bytes calldata _lookahead,
uint48 _nextProposalId,
uint48 _lastProposalBlockId,
uint48 _lastFinalizedProposalId
)
private
returns (Proposal memory proposal_, Derivation memory derivation_)
{
unchecked {
// Enforce one propose call per Ethereum block to prevent spam attacks that could
// deplete the ring buffer
require(block.number > _lastProposalBlockId, CannotProposeInCurrentBlock());
require(
_getAvailableCapacity(_nextProposalId, _lastFinalizedProposalId) > 0,
NotEnoughCapacity()
);
ConsumptionResult memory result =
_consumeForcedInclusions(msg.sender, _input.numForcedInclusions);
result.sources[result.sources.length - 1] =
DerivationSource(false, LibBlobs.validateBlobReference(_input.blobReference));
// If forced inclusion is old enough, allow anyone to propose
// and set endOfSubmissionWindowTimestamp = 0
// Otherwise, only the current preconfer can propose
uint48 endOfSubmissionWindowTimestamp = result.allowsPermissionless
? 0
: _proposerChecker.checkProposer(msg.sender, _lookahead);
// Use previous block as the origin for the proposal to be able to call `blockhash`
uint256 parentBlockNumber = block.number - 1;
derivation_ = Derivation({
originBlockNumber: uint48(parentBlockNumber),
originBlockHash: blockhash(parentBlockNumber),
basefeeSharingPctg: _basefeeSharingPctg,
sources: result.sources
});
proposal_ = Proposal({
id: _nextProposalId,
timestamp: uint48(block.timestamp),
endOfSubmissionWindowTimestamp: endOfSubmissionWindowTimestamp,
proposer: msg.sender,
parentProposalHash: getProposalHash(_nextProposalId - 1),
derivationHash: LibHashOptimized.hashDerivation(derivation_)
});
}
}
/// @dev Stores a proposal hash in the ring buffer
/// Overwrites any existing hash at the calculated buffer slot
function _setProposalHash(uint48 _proposalId, bytes32 _proposalHash) private {
_proposalHashes[_proposalId % _ringBufferSize] = _proposalHash;
}
/// @dev Consumes forced inclusions from the queue and returns result with extra slot for normal
/// source
/// @param _feeRecipient Address to receive accumulated fees
/// @param _numForcedInclusionsRequested Maximum number of forced inclusions to consume
/// @return result_ ConsumptionResult with sources array (size: processed + 1, last slot empty)
/// and whether permissionless proposals are allowed
function _consumeForcedInclusions(
address _feeRecipient,
uint256 _numForcedInclusionsRequested
)
private
returns (ConsumptionResult memory result_)
{
unchecked {
LibForcedInclusion.Storage storage $ = _forcedInclusionStorage;
// Load storage once
(uint48 head, uint48 tail) = ($.head, $.tail);
uint256 available = tail - head;
uint256 toProcess = _numForcedInclusionsRequested > available
? available
: _numForcedInclusionsRequested;
result_.sources = new DerivationSource[](toProcess + 1);
uint48 oldestTimestamp;
(oldestTimestamp, head) = _dequeueAndProcessForcedInclusions(
$, _feeRecipient, result_.sources, head, toProcess
);
// We check the following conditions are met:
// 1. Proposer is willing to include at least the minimum required
// (_minForcedInclusionCount) OR
// 2. Proposer included all available inclusions that are due
if (_numForcedInclusionsRequested < _minForcedInclusionCount && available > toProcess) {
bool isOldestInclusionDue = LibForcedInclusion.isOldestForcedInclusionDue(
$, head, tail, _forcedInclusionDelay
);
require(!isOldestInclusionDue, UnprocessedForcedInclusionIsDue());
}
uint256 permissionlessTimestamp = uint256(_forcedInclusionDelay)
* _permissionlessInclusionMultiplier + oldestTimestamp;
result_.allowsPermissionless = block.timestamp > permissionlessTimestamp;
}
}
/// @dev Dequeues and processes forced inclusions from the queue without checking if they exist
/// @param $ Storage reference
/// @param _feeRecipient Address to receive fees
/// @param _sources Array to populate with derivation sources
/// @param _head Current queue head position
/// @param _toProcess Number of inclusions to process
/// @return oldestTimestamp_ Oldest timestamp from processed inclusions.
/// `type(uint48).max` if no inclusions were processed
/// @return head_ Updated head position
function _dequeueAndProcessForcedInclusions(
LibForcedInclusion.Storage storage $,
address _feeRecipient,
DerivationSource[] memory _sources,
uint48 _head,
uint256 _toProcess
)
private
returns (uint48 oldestTimestamp_, uint48 head_)
{
unchecked {
if (_toProcess == 0) {
return (type(uint48).max, _head);
}
// Process inclusions and accumulate fees
uint256 totalFees;
for (uint256 i; i < _toProcess; ++i) {
IForcedInclusionStore.ForcedInclusion storage inclusion = $.queue[_head + i];
_sources[i] = IInbox.DerivationSource(true, inclusion.blobSlice);
totalFees += inclusion.feeInGwei;
}
// Transfer accumulated fees
if (totalFees > 0) {
_feeRecipient.sendEtherAndVerify(totalFees * 1 gwei);
}
// Oldest timestamp is the timestamp of the first inclusion
oldestTimestamp_ = uint48(_sources[0].blobSlice.timestamp);
// Update queue position
head_ = _head + uint48(_toProcess);
// Write to storage once
$.head = head_;
}
}
/// @dev Calculates and emits bond instruction if applicable.
/// @dev Bond instruction rules:
/// - On-time (within provingWindow + sequential grace): No bond changes.
/// - Late: Liveness bond transfer, even when the designated and actual provers are the
/// same address (L2 processing handles slashing/reward splits).
/// @param _commitment The commitment data.
/// @param _offset The offset to the first unfinalized proposal.
function _processBondInstruction(
Commitment memory _commitment,
uint48 _offset
)
private
{
unchecked {
uint256 livenessWindowDeadline = (_commitment.transitions[_offset].timestamp
+ _provingWindow)
.max(_coreState.lastFinalizedTimestamp + _maxProofSubmissionDelay);
// On-time proof - no bond transfer needed.
if (block.timestamp <= livenessWindowDeadline) {
return;
}
LibBonds.BondInstruction memory bondInstruction = LibBonds.BondInstruction({
proposalId: _commitment.firstProposalId + _offset,
bondType: LibBonds.BondType.LIVENESS,
payer: _commitment.transitions[_offset].designatedProver,
payee: _commitment.actualProver
});
_signalService.sendSignal(LibBonds.hashBondInstruction(bondInstruction));
emit BondInstructionCreated(bondInstruction.proposalId, bondInstruction);
}
}
/// @dev Emits the Proposed event
function _emitProposedEvent(
Proposal memory _proposal,
Derivation memory _derivation
)
private
{
ProposedEventPayload memory payload =
ProposedEventPayload({ proposal: _proposal, derivation: _derivation });
emit Proposed(LibProposedEventCodec.encode(payload));
}
// ---------------------------------------------------------------
// Private View/Pure Functions
// ---------------------------------------------------------------
/// @dev Calculates remaining capacity for new proposals
/// Subtracts unfinalized proposals from total capacity
/// @param _nextProposalId The next proposal ID
/// @param _lastFinalizedProposalId The ID of the last finalized proposal
/// @return _ Number of additional proposals that can be submitted
function _getAvailableCapacity(
uint48 _nextProposalId,
uint48 _lastFinalizedProposalId
)
private
view
returns (uint256)
{
unchecked {
uint256 numUnfinalizedProposals = _nextProposalId - _lastFinalizedProposalId - 1;
return _ringBufferSize - 1 - numUnfinalizedProposals;
}
}
/// @dev Validates propose function inputs.
/// @param _input The ProposeInput to validate
function _validateProposeInput(ProposeInput memory _input) private view {
require(_input.deadline == 0 || block.timestamp <= _input.deadline, DeadlineExceeded());
}
/// @dev Checks if the caller is an authorized prover
/// @param _addr The address of the caller to check
/// @return whitelistEnabled_ True if whitelist is enabled (proverCount > 0), false otherwise
function _checkProver(address _addr) private view returns (bool whitelistEnabled_) {
if (address(_proverWhitelist) == address(0)) return false;
(bool isWhitelisted, uint256 proverCount) = _proverWhitelist.isProverWhitelisted(_addr);
if (proverCount == 0) return false;
require(isWhitelisted, ProverNotWhitelisted());
return true;
}
/// @dev Validates the batch bounds in the Commitment and calculates the offset
/// to the first unfinalized proposal.
/// @param _state The core state.
/// @param _commitment The commitment data.
/// @return numProposals_ The number of proposals in the batch.
/// @return lastProposalId_ The ID of the last proposal in the batch.
/// @return offset_ The offset to the first unfinalized proposal.
function _validateCommitment(
CoreState memory _state,
Commitment memory _commitment
)
private
pure
returns (uint256 numProposals_, uint256 lastProposalId_, uint48 offset_)
{
unchecked {
uint256 firstUnfinalizedId = _state.lastFinalizedProposalId + 1;
numProposals_ = _commitment.transitions.length;
require(numProposals_ > 0, EmptyBatch());
require(_commitment.firstProposalId <= firstUnfinalizedId, FirstProposalIdTooLarge());
lastProposalId_ = _commitment.firstProposalId + numProposals_ - 1;
require(lastProposalId_ < _state.nextProposalId, LastProposalIdTooLarge());
require(lastProposalId_ >= firstUnfinalizedId, LastProposalAlreadyFinalized());
// Calculate offset to first unfinalized proposal.
// Some proposals in _commitment.transitions[] may already be finalized.
// The offset points to the first proposal that will be finalized.
offset_ = uint48(firstUnfinalizedId - _commitment.firstProposalId);
}
}
// ---------------------------------------------------------------
// Errors
// ---------------------------------------------------------------
error ActivationRequired();
error CannotProposeInCurrentBlock();
error CheckpointDelayHasPassed();
error DeadlineExceeded();
error EmptyBatch();
error FirstProposalIdTooLarge();
error IncorrectProposalCount();
error LastProposalAlreadyFinalized();
error LastProposalHashMismatch();
error LastProposalIdTooLarge();
error NotEnoughCapacity();
error ParentBlockHashMismatch();
error ProverNotWhitelisted();
error UnprocessedForcedInclusionIsDue();
}
node_modules/@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}
node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./OwnableUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function __Ownable2Step_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable2Step_init_unchained() internal onlyInitializing {
}
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
contracts/layer1/core/libs/LibProposedEventCodec.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IInbox } from "../iface/IInbox.sol";
import { LibPackUnpack as P } from "./LibPackUnpack.sol";
/// @title LibProposedEventCodec
/// @notice Compact encoder/decoder for ProposedEventPayload using LibPackUnpack.
/// @custom:security-contact security@taiko.xyz
library LibProposedEventCodec {
/// @notice Encodes a ProposedEventPayload into bytes using compact encoding.
function encode(IInbox.ProposedEventPayload memory _payload)
internal
pure
returns (bytes memory encoded_)
{
uint256 bufferSize = calculateProposedEventSize(_payload.derivation.sources);
encoded_ = new bytes(bufferSize);
uint256 ptr = P.dataPtr(encoded_);
ptr = P.packUint48(ptr, _payload.proposal.id);
ptr = P.packAddress(ptr, _payload.proposal.proposer);
ptr = P.packUint48(ptr, _payload.proposal.timestamp);
ptr = P.packUint48(ptr, _payload.proposal.endOfSubmissionWindowTimestamp);
ptr = P.packBytes32(ptr, _payload.proposal.parentProposalHash);
ptr = P.packUint48(ptr, _payload.derivation.originBlockNumber);
ptr = P.packBytes32(ptr, _payload.derivation.originBlockHash);
ptr = P.packUint8(ptr, _payload.derivation.basefeeSharingPctg);
uint256 sourcesLength = _payload.derivation.sources.length;
P.checkArrayLength(sourcesLength);
ptr = P.packUint16(ptr, uint16(sourcesLength));
for (uint256 i; i < sourcesLength; ++i) {
IInbox.DerivationSource memory source = _payload.derivation.sources[i];
ptr = P.packUint8(ptr, source.isForcedInclusion ? 1 : 0);
uint256 blobHashesLength = source.blobSlice.blobHashes.length;
P.checkArrayLength(blobHashesLength);
ptr = P.packUint16(ptr, uint16(blobHashesLength));
for (uint256 j; j < blobHashesLength; ++j) {
ptr = P.packBytes32(ptr, source.blobSlice.blobHashes[j]);
}
ptr = P.packUint24(ptr, source.blobSlice.offset);
ptr = P.packUint48(ptr, source.blobSlice.timestamp);
}
ptr = P.packBytes32(ptr, _payload.proposal.derivationHash);
}
/// @notice Decodes bytes into a ProposedEventPayload using compact encoding.
function decode(bytes memory _data)
internal
pure
returns (IInbox.ProposedEventPayload memory payload_)
{
uint256 ptr = P.dataPtr(_data);
(payload_.proposal.id, ptr) = P.unpackUint48(ptr);
(payload_.proposal.proposer, ptr) = P.unpackAddress(ptr);
(payload_.proposal.timestamp, ptr) = P.unpackUint48(ptr);
(payload_.proposal.endOfSubmissionWindowTimestamp, ptr) = P.unpackUint48(ptr);
(payload_.proposal.parentProposalHash, ptr) = P.unpackBytes32(ptr);
(payload_.derivation.originBlockNumber, ptr) = P.unpackUint48(ptr);
(payload_.derivation.originBlockHash, ptr) = P.unpackBytes32(ptr);
(payload_.derivation.basefeeSharingPctg, ptr) = P.unpackUint8(ptr);
uint16 sourcesLength;
(sourcesLength, ptr) = P.unpackUint16(ptr);
payload_.derivation.sources = new IInbox.DerivationSource[](sourcesLength);
for (uint256 i; i < sourcesLength; ++i) {
uint8 isForcedInclusion;
(isForcedInclusion, ptr) = P.unpackUint8(ptr);
payload_.derivation.sources[i].isForcedInclusion = isForcedInclusion != 0;
uint16 blobHashesLength;
(blobHashesLength, ptr) = P.unpackUint16(ptr);
payload_.derivation.sources[i].blobSlice.blobHashes = new bytes32[](blobHashesLength);
for (uint256 j; j < blobHashesLength; ++j) {
(payload_.derivation.sources[i].blobSlice.blobHashes[j], ptr) = P.unpackBytes32(ptr);
}
(payload_.derivation.sources[i].blobSlice.offset, ptr) = P.unpackUint24(ptr);
(payload_.derivation.sources[i].blobSlice.timestamp, ptr) = P.unpackUint48(ptr);
}
(payload_.proposal.derivationHash, ptr) = P.unpackBytes32(ptr);
}
/// @notice Calculate the exact byte size needed for encoding a ProposedEventPayload.
function calculateProposedEventSize(IInbox.DerivationSource[] memory _sources)
internal
pure
returns (uint256 size_)
{
unchecked {
// Fixed size without sources: 143 bytes
// Proposal: id(6) + proposer(20) + timestamp(6) + endOfSubmissionWindowTimestamp(6) +
// parentProposalHash(32)
// Derivation base: originBlockNumber(6) + originBlockHash(32) + basefeeSharingPctg(1)
// Sources length: 2
// Proposal hash: derivationHash(32)
size_ = 143;
for (uint256 i; i < _sources.length; ++i) {
size_ += 12 + (_sources[i].blobSlice.blobHashes.length * 32);
}
}
}
}
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/@openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}
contracts/shared/signal/ICheckpointStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title ICheckpointStore
/// @notice Interface for storing and retrieving checkpoints
/// @custom:security-contact security@taiko.xyz
interface ICheckpointStore {
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @notice Represents a synced checkpoint
struct Checkpoint {
/// @notice The block number associated with the checkpoint.
uint48 blockNumber;
/// @notice The block hash for the end (last) L2 block in this proposal.
bytes32 blockHash;
/// @notice The state root for the end (last) L2 block in this proposal.
bytes32 stateRoot;
}
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
/// @notice Emitted when a checkpoint is saved
/// @param blockNumber The block number
/// @param blockHash The block hash
/// @param stateRoot The state root
event CheckpointSaved(uint48 indexed blockNumber, bytes32 blockHash, bytes32 stateRoot);
// ---------------------------------------------------------------
// External Functions
// ---------------------------------------------------------------
/// @notice Saves a checkpoint
/// @param _checkpoint The checkpoint data to persist
function saveCheckpoint(Checkpoint calldata _checkpoint) external;
/// @notice Gets a checkpoint by its block number
/// @param _blockNumber The block number associated with the checkpoint
/// @return _ The checkpoint
function getCheckpoint(uint48 _blockNumber) external view returns (Checkpoint memory);
}
contracts/layer1/core/libs/LibPackUnpack.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title LibPackUnpack
/// @notice Library providing low-level packing/unpacking functions for compact binary encoding
/// using inline assembly for maximum gas efficiency.
/// @dev This library implements a trust-the-caller pattern with no bounds checking for optimal
/// performance. Callers are responsible for:
/// - Allocating sufficient memory for pack operations
/// - Ensuring data has sufficient length for unpack operations
/// - Tracking position offsets correctly
///
/// Memory Layout:
/// - Pack functions write directly to memory at absolute positions
/// - Unpack functions read from memory at absolute positions
/// - All multi-byte integers use big-endian encoding
/// - Position tracking is left to the caller
///
/// Safety Notes:
/// - No overflow protection on position increments (caller's responsibility)
/// - No bounds checking on memory access (gas-optimized design)
/// - Suitable for controlled environments where input validation happens upstream
///
/// Usage Example:
/// ```solidity
/// bytes memory buffer = new bytes(100);
/// uint256 pos = LibPackUnpack.dataPtr(buffer);
/// pos = LibPackUnpack.packUint32(pos, 12345);
/// pos = LibPackUnpack.packAddress(pos, msg.sender);
/// ```
/// @custom:security-contact security@taiko.xyz
library LibPackUnpack {
// ---------------------------------------------------------------
// Pack Functions (write to buffer with compact encoding)
// ---------------------------------------------------------------
/// @notice Pack uint8 (1 byte) at position
/// @dev Writes a single byte to memory at the specified position.
/// @param _pos Absolute memory position to write at
/// @param _value The uint8 value to pack (0-255)
/// @return newPos_ Updated position after writing (pos + 1)
function packUint8(uint256 _pos, uint8 _value) internal pure returns (uint256 newPos_) {
assembly {
mstore8(_pos, _value)
newPos_ := add(_pos, 1)
}
}
/// @notice Pack uint16 (2 bytes) at position using big-endian encoding
/// @dev Optimized to use mstore instead of 2 individual mstore8 operations.
/// @param _pos Absolute memory position to write at
/// @param _value The uint16 value to pack (0-65535)
/// @return newPos_ Updated position after writing (pos + 2)
function packUint16(uint256 _pos, uint16 _value) internal pure returns (uint256 newPos_) {
assembly {
// Shift value left by 30 bytes (240 bits) to align at the start of a 32-byte word
let shifted := shl(240, _value)
// Store the shifted value at position
mstore(_pos, shifted)
newPos_ := add(_pos, 2)
}
}
/// @notice Pack uint24 (3 bytes) at position using big-endian encoding
/// @dev Optimized to use mstore instead of 3 individual mstore8 operations.
/// @param _pos Absolute memory position to write at
/// @param _value The uint24 value to pack (0-16777215)
/// @return newPos_ Updated position after writing (pos + 3)
function packUint24(uint256 _pos, uint24 _value) internal pure returns (uint256 newPos_) {
assembly {
// Shift value left by 29 bytes (232 bits) to align at the start of a 32-byte word
let shifted := shl(232, _value)
// Store the shifted value at position
mstore(_pos, shifted)
newPos_ := add(_pos, 3)
}
}
/// @notice Pack uint32 (4 bytes) at position using big-endian encoding
/// @dev Optimized to use mstore instead of 4 individual mstore8 operations.
/// @param _pos Absolute memory position to write at
/// @param _value The uint32 value to pack (0-4294967295)
/// @return newPos_ Updated position after writing (pos + 4)
function packUint32(uint256 _pos, uint32 _value) internal pure returns (uint256 newPos_) {
assembly {
// Shift value left by 28 bytes (224 bits) to align at the start of a 32-byte word
let shifted := shl(224, _value)
// Store the shifted value at position
mstore(_pos, shifted)
newPos_ := add(_pos, 4)
}
}
/// @notice Pack uint48 (6 bytes) at position using big-endian encoding
/// @dev Optimized to use mstore instead of 6 individual mstore8 operations.
/// Common use case: block numbers that exceed uint32 range.
/// @param _pos Absolute memory position to write at
/// @param _value The uint48 value to pack (0-281474976710655)
/// @return newPos_ Updated position after writing (pos + 6)
function packUint48(uint256 _pos, uint48 _value) internal pure returns (uint256 newPos_) {
assembly {
// Shift value left by 26 bytes (208 bits) to align at the start of a 32-byte word
let shifted := shl(208, _value)
// Store the shifted value at position
mstore(_pos, shifted)
newPos_ := add(_pos, 6)
}
}
/// @notice Pack uint256 (32 bytes) at position
/// @dev Uses single mstore for efficiency, writes full 32-byte word.
/// @param _pos Absolute memory position to write at (best if 32-byte aligned)
/// @param _value The uint256 value to pack
/// @return newPos_ Updated position after writing (pos + 32)
function packUint256(
uint256 _pos,
uint256 _value
)
internal
pure
returns (uint256 newPos_)
{
assembly {
mstore(_pos, _value)
newPos_ := add(_pos, 32)
}
}
/// @notice Pack bytes32 at position
/// @dev Direct 32-byte write, commonly used for hashes and identifiers.
/// @param _pos Absolute memory position to write at (best if 32-byte aligned)
/// @param _value The bytes32 value to pack (hash, identifier, etc.)
/// @return newPos_ Updated position after writing (pos + 32)
function packBytes32(
uint256 _pos,
bytes32 _value
)
internal
pure
returns (uint256 newPos_)
{
assembly {
mstore(_pos, _value)
newPos_ := add(_pos, 32)
}
}
/// @notice Pack address (20 bytes) at position
/// @dev Optimized to use mstore instead of 20 individual mstore8 operations.
/// Handles alignment by using a single mstore with proper shifting.
/// @param _pos Absolute memory position to write at
/// @param _value The address to pack
/// @return newPos_ Updated position after writing (pos + 20)
function packAddress(
uint256 _pos,
address _value
)
internal
pure
returns (uint256 newPos_)
{
assembly {
// Shift address left by 12 bytes (96 bits) to align it properly in a 32-byte word
// This places the 20-byte address at the start of the word with 12 bytes of padding
let shifted := shl(96, _value)
// Store the shifted address at position
// This writes 32 bytes, but we only care about the first 20
mstore(_pos, shifted)
newPos_ := add(_pos, 20)
}
}
// ---------------------------------------------------------------
// Unpack Functions (read from buffer with compact encoding)
// ---------------------------------------------------------------
/// @notice Unpack uint8 (1 byte) from position
/// @dev Optimized to use shift operation instead of byte operation.
/// @param _pos Absolute memory position to read from
/// @return value_ The unpacked uint8 value
/// @return newPos_ Updated position after reading (pos + 1)
function unpackUint8(uint256 _pos) internal pure returns (uint8 value_, uint256 newPos_) {
assembly {
// Load full word and shift right by 248 bits (31 bytes) to get the 1 byte we need
value_ := shr(248, mload(_pos))
newPos_ := add(_pos, 1)
}
}
/// @notice Unpack uint16 (2 bytes) from position using big-endian encoding
/// @dev Optimized to use 1 mload operation instead of 2 byte reads.
/// @param _pos Absolute memory position to read from
/// @return value_ The unpacked uint16 value
/// @return newPos_ Updated position after reading (pos + 2)
function unpackUint16(uint256 _pos) internal pure returns (uint16 value_, uint256 newPos_) {
assembly {
// Load full word and shift right by 240 bits (30 bytes) to get the 2 bytes we need
value_ := shr(240, mload(_pos))
newPos_ := add(_pos, 2)
}
}
/// @notice Unpack uint24 (3 bytes) from position using big-endian encoding
/// @dev Optimized to use 1 mload operation instead of 3 byte reads.
/// @param _pos Absolute memory position to read from
/// @return value_ The unpacked uint24 value
/// @return newPos_ Updated position after reading (pos + 3)
function unpackUint24(uint256 _pos) internal pure returns (uint24 value_, uint256 newPos_) {
assembly {
// Load full word and shift right by 232 bits (29 bytes) to get the 3 bytes we need
value_ := shr(232, mload(_pos))
newPos_ := add(_pos, 3)
}
}
/// @notice Unpack uint32 (4 bytes) from position using big-endian encoding
/// @dev Optimized to use 1 mload operation instead of 4 byte reads.
/// @param _pos Absolute memory position to read from
/// @return value_ The unpacked uint32 value
/// @return newPos_ Updated position after reading (pos + 4)
function unpackUint32(uint256 _pos) internal pure returns (uint32 value_, uint256 newPos_) {
assembly {
// Load full word and shift right by 224 bits (28 bytes) to get the 4 bytes we need
value_ := shr(224, mload(_pos))
newPos_ := add(_pos, 4)
}
}
/// @notice Unpack uint48 (6 bytes) from position using big-endian encoding
/// @dev Optimized to use 1 mload operation instead of 6 byte reads.
/// @param _pos Absolute memory position to read from
/// @return value_ The unpacked uint48 value
/// @return newPos_ Updated position after reading (pos + 6)
function unpackUint48(uint256 _pos) internal pure returns (uint48 value_, uint256 newPos_) {
assembly {
// Load full word and shift right by 208 bits (26 bytes) to get the 6 bytes we need
value_ := shr(208, mload(_pos))
newPos_ := add(_pos, 6)
}
}
/// @notice Unpack uint256 (32 bytes) from position
/// @dev Single mload for efficiency. Reads full 32-byte word.
/// @param _pos Absolute memory position to read from (best if 32-byte aligned)
/// @return value_ The unpacked uint256 value
/// @return newPos_ Updated position after reading (pos + 32)
function unpackUint256(uint256 _pos) internal pure returns (uint256 value_, uint256 newPos_) {
assembly {
value_ := mload(_pos)
newPos_ := add(_pos, 32)
}
}
/// @notice Unpack bytes32 from position
/// @dev Direct 32-byte read for hashes and identifiers.
/// @param _pos Absolute memory position to read from (best if 32-byte aligned)
/// @return value_ The unpacked bytes32 value
/// @return newPos_ Updated position after reading (pos + 32)
function unpackBytes32(uint256 _pos) internal pure returns (bytes32 value_, uint256 newPos_) {
assembly {
value_ := mload(_pos)
newPos_ := add(_pos, 32)
}
}
/// @notice Unpack address (20 bytes) from position
/// @dev Optimized to use only 1 mload operation instead of 20 individual byte reads.
/// Reads one full word and shifts to extract the address bytes.
/// @param _pos Absolute memory position to read from
/// @return value_ The unpacked address
/// @return newPos_ Updated position after reading (pos + 20)
function unpackAddress(uint256 _pos) internal pure returns (address value_, uint256 newPos_) {
assembly {
// Load the full 32-byte word starting at _pos
let word := mload(_pos)
// Shift right by 96 bits (12 bytes) to align the 20-byte address to the right
// This removes the 12 trailing bytes and keeps the first 20 bytes
value_ := shr(96, word)
newPos_ := add(_pos, 20)
}
}
// ---------------------------------------------------------------
// Utility Functions
// ---------------------------------------------------------------
/// @notice Get the memory pointer to the data section of a bytes array
/// @dev Skips the 32-byte length prefix to point at actual data.
/// Essential for converting bytes memory to absolute position for pack/unpack operations.
/// @param _data The bytes array to get data pointer from
/// @return ptr_ The absolute memory pointer to the actual data (data location + 0x20)
function dataPtr(bytes memory _data) internal pure returns (uint256 ptr_) {
assembly {
ptr_ := add(_data, 0x20)
}
}
/// @notice Check that an array length fits within uint16 bounds
/// @dev Reverts if the length exceeds uint16 maximum value (65535).
/// Useful as a validation guard before packing array lengths.
/// @param _length The array length to validate
function checkArrayLength(uint256 _length) internal pure {
require(_length <= type(uint16).max, LengthExceedsUint16());
}
// ---------------------------------------------------------------
// Errors
// ---------------------------------------------------------------
error LengthExceedsUint16();
}
contracts/layer1/core/libs/LibProposeInputCodec.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IInbox } from "../iface/IInbox.sol";
import { LibPackUnpack as P } from "./LibPackUnpack.sol";
/// @title LibProposeInputCodec
/// @notice Compact encoder/decoder for propose inputs using LibPackUnpack.
/// @custom:security-contact security@taiko.xyz
library LibProposeInputCodec {
/// @notice Encodes propose data using compact packing.
function encode(IInbox.ProposeInput memory _input)
internal
pure
returns (bytes memory encoded_)
{
encoded_ = new bytes(14);
uint256 ptr = P.dataPtr(encoded_);
ptr = P.packUint48(ptr, _input.deadline);
ptr = P.packUint16(ptr, _input.blobReference.blobStartIndex);
ptr = P.packUint16(ptr, _input.blobReference.numBlobs);
ptr = P.packUint24(ptr, _input.blobReference.offset);
ptr = P.packUint8(ptr, _input.numForcedInclusions);
}
/// @notice Decodes propose data using compact packing.
function decode(bytes memory _data) internal pure returns (IInbox.ProposeInput memory input_) {
uint256 ptr = P.dataPtr(_data);
(input_.deadline, ptr) = P.unpackUint48(ptr);
(input_.blobReference.blobStartIndex, ptr) = P.unpackUint16(ptr);
(input_.blobReference.numBlobs, ptr) = P.unpackUint16(ptr);
(input_.blobReference.offset, ptr) = P.unpackUint24(ptr);
(input_.numForcedInclusions, ptr) = P.unpackUint8(ptr);
}
}
node_modules/@openzeppelin/contracts/interfaces/IERC1967.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}
node_modules/@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
contracts/shared/libs/LibAddress.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/// @title LibAddress
/// @dev Provides utilities for address-related operations.
/// @custom:security-contact security@taiko.xyz
library LibAddress {
error ETH_TRANSFER_FAILED();
/// @dev Sends Ether to the specified address. This method will not revert even if sending ether
/// fails.
/// This function is inspired by
/// https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol
/// @param _to The recipient address.
/// @param _amount The amount of Ether to send in wei.
/// @param _gasLimit The max amount gas to pay for this transaction.
/// @return success_ true if the call is successful, false otherwise.
function sendEther(
address _to,
uint256 _amount,
uint256 _gasLimit,
bytes memory _calldata
)
internal
returns (bool success_)
{
// Check for zero-address transactions
require(_to != address(0), ETH_TRANSFER_FAILED());
// dispatch message to recipient
// by assembly calling "handle" function
// we call via assembly to avoid memcopying a very large returndata
// returned by a malicious contract
assembly ("memory-safe") {
success_ := call(
_gasLimit, // gas
_to, // recipient
_amount, // ether value
add(_calldata, 0x20), // inloc
mload(_calldata), // inlen
0, // outloc
0 // outlen
)
}
}
/// @dev Sends Ether to the specified address. This method will revert if sending ether fails.
/// @param _to The recipient address.
/// @param _amount The amount of Ether to send in wei.
/// @param _gasLimit The max amount gas to pay for this transaction.
function sendEtherAndVerify(address _to, uint256 _amount, uint256 _gasLimit) internal {
if (_amount == 0) return;
require(sendEther(_to, _amount, _gasLimit, ""), ETH_TRANSFER_FAILED());
}
/// @dev Sends Ether to the specified address. This method will revert if sending ether fails.
/// @param _to The recipient address.
/// @param _amount The amount of Ether to send in wei.
function sendEtherAndVerify(address _to, uint256 _amount) internal {
sendEtherAndVerify(_to, _amount, gasleft());
}
function supportsInterface(
address _addr,
bytes4 _interfaceId
)
internal
view
returns (bool result_)
{
(bool success, bytes memory data) =
_addr.staticcall(abi.encodeCall(IERC165.supportsInterface, (_interfaceId)));
if (success && data.length == 32) {
result_ = abi.decode(data, (bool));
}
}
}
contracts/shared/common/EssentialContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "./IResolver.sol";
import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
/// @title EssentialContract
/// @custom:security-contact security@taiko.xyz
abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable {
// ---------------------------------------------------------------
// Constants and Immutable Variables
// ---------------------------------------------------------------
uint8 internal constant _FALSE = 1;
uint8 internal constant _TRUE = 2;
address internal immutable __resolver;
// ---------------------------------------------------------------
// State Variables
// ---------------------------------------------------------------
uint256[50] private __gapFromOldAddressResolver;
/// @dev Slot 1.
uint8 internal __reentry;
uint8 internal __paused;
uint256[49] private __gap;
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
/// @notice Emitted when the contract is paused.
/// @param account The account that paused the contract.
event Paused(address account);
/// @notice Emitted when the contract is unpaused.
/// @param account The account that unpaused the contract.
event Unpaused(address account);
error INVALID_PAUSE_STATUS();
error FUNC_NOT_IMPLEMENTED();
error REENTRANT_CALL();
error ACCESS_DENIED();
error ZERO_ADDRESS();
error ZERO_VALUE();
// ---------------------------------------------------------------
// Modifiers
// ---------------------------------------------------------------
/// @dev Modifier that ensures the caller is either the owner or a specified address.
/// @param _addr The address to check against.
modifier onlyFromOwnerOr(address _addr) {
_checkOwnerOr(_addr);
_;
}
/// @dev Modifier that reverts the function call, indicating it is not implemented.
modifier notImplemented() {
revert FUNC_NOT_IMPLEMENTED();
_;
}
/// @dev Modifier that prevents reentrant calls to a function.
modifier nonReentrant() {
_checkReentrancy();
_storeReentryLock(_TRUE);
_;
_storeReentryLock(_FALSE);
}
/// @dev Modifier that allows function execution only when the contract is paused.
modifier whenPaused() {
_checkPaused();
_;
}
/// @dev Modifier that allows function execution only when the contract is not paused.
modifier whenNotPaused() {
_checkNotPaused();
_;
}
/// @dev Modifier that ensures the provided address is not the zero address.
/// @param _addr The address to check.
modifier nonZeroAddr(address _addr) {
_checkNonZeroAddr(_addr);
_;
}
/// @dev Modifier that ensures the provided value is not zero.
/// @param _value The value to check.
modifier nonZeroValue(uint256 _value) {
_checkNonZeroValue(_value);
_;
}
/// @dev Modifier that ensures the provided bytes32 value is not zero.
/// @param _value The bytes32 value to check.
modifier nonZeroBytes32(bytes32 _value) {
_checkNonZeroBytes32(_value);
_;
}
/// @dev Modifier that ensures the caller is either of the two specified addresses.
/// @param _addr1 The first address to check against.
/// @param _addr2 The second address to check against.
modifier onlyFromEither(address _addr1, address _addr2) {
_checkFromEither(_addr1, _addr2);
_;
}
/// @dev Modifier that ensures the caller is the specified address.
/// @param _addr The address to check against.
modifier onlyFrom(address _addr) {
_checkFrom(_addr);
_;
}
/// @dev Modifier that ensures the caller is the specified address.
/// @param _addr The address to check against.
modifier onlyFromOptional(address _addr) {
_checkFromOptional(_addr);
_;
}
// ---------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------
constructor() {
_disableInitializers();
}
// ---------------------------------------------------------------
// External & Public Functions
// ---------------------------------------------------------------
/// @notice Pauses the contract.
function pause() public whenNotPaused {
_pause();
emit Paused(msg.sender);
// We call the authorize function here to avoid:
// Warning (5740): Unreachable code.
_authorizePause(msg.sender, true);
}
/// @notice Unpauses the contract.
function unpause() public whenPaused {
_unpause();
emit Unpaused(msg.sender);
// We call the authorize function here to avoid:
// Warning (5740): Unreachable code.
_authorizePause(msg.sender, false);
}
function impl() public view returns (address) {
return _getImplementation();
}
/// @notice Returns true if the contract is paused, and false otherwise.
/// @return true if paused, false otherwise.
function paused() public view virtual returns (bool) {
return __paused == _TRUE;
}
function inNonReentrant() public view returns (bool) {
return _loadReentryLock() == _TRUE;
}
/// @notice Returns the address of this contract.
/// @return The address of this contract.
function resolver() public view virtual returns (address) {
return __resolver;
}
// ---------------------------------------------------------------
// Internal Functions
// ---------------------------------------------------------------
/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
function __Essential_init(address _owner) internal virtual onlyInitializing {
__Context_init();
_transferOwnership(_owner == address(0) ? msg.sender : _owner);
__paused = _FALSE;
}
function _pause() internal virtual {
__paused = _TRUE;
}
function _unpause() internal virtual {
__paused = _FALSE;
}
function _authorizeUpgrade(address) internal virtual override onlyOwner { }
function _authorizePause(address, bool) internal virtual onlyOwner { }
// Stores the reentry lock
function _storeReentryLock(uint8 _reentry) internal virtual {
__reentry = _reentry;
}
// Loads the reentry lock
function _loadReentryLock() internal view virtual returns (uint8 reentry_) {
reentry_ = __reentry;
}
// ---------------------------------------------------------------
// Private Functions
// ---------------------------------------------------------------
function _checkOwnerOr(address _addr) private view {
require(msg.sender == owner() || msg.sender == _addr, ACCESS_DENIED());
}
function _checkReentrancy() private view {
require(_loadReentryLock() != _TRUE, REENTRANT_CALL());
}
function _checkPaused() private view {
require(paused(), INVALID_PAUSE_STATUS());
}
function _checkNotPaused() private view {
require(!paused(), INVALID_PAUSE_STATUS());
}
function _checkNonZeroAddr(address _addr) private pure {
require(_addr != address(0), ZERO_ADDRESS());
}
function _checkNonZeroValue(uint256 _value) private pure {
require(_value != 0, ZERO_VALUE());
}
function _checkNonZeroBytes32(bytes32 _value) private pure {
require(_value != 0, ZERO_VALUE());
}
function _checkFromEither(address _addr1, address _addr2) private view {
require(msg.sender == _addr1 || msg.sender == _addr2, ACCESS_DENIED());
}
function _checkFrom(address _addr) private view {
require(msg.sender == _addr, ACCESS_DENIED());
}
function _checkFromOptional(address _addr) private view {
require(_addr == address(0) || msg.sender == _addr, ACCESS_DENIED());
}
}
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));
}
}
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/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();
}
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":{},"evmVersion":"prague"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"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":"address","name":"_codec","internalType":"address"}]},{"type":"error","name":"ACCESS_DENIED","inputs":[]},{"type":"error","name":"ActivationRequired","inputs":[]},{"type":"error","name":"BlobNotFound","inputs":[]},{"type":"error","name":"CannotProposeInCurrentBlock","inputs":[]},{"type":"error","name":"CheckpointDelayHasPassed","inputs":[]},{"type":"error","name":"DeadlineExceeded","inputs":[]},{"type":"error","name":"ETH_TRANSFER_FAILED","inputs":[]},{"type":"error","name":"EmptyBatch","inputs":[]},{"type":"error","name":"FUNC_NOT_IMPLEMENTED","inputs":[]},{"type":"error","name":"FirstProposalIdTooLarge","inputs":[]},{"type":"error","name":"INVALID_PAUSE_STATUS","inputs":[]},{"type":"error","name":"IncorrectProposalCount","inputs":[]},{"type":"error","name":"LastProposalAlreadyFinalized","inputs":[]},{"type":"error","name":"LastProposalHashMismatch","inputs":[]},{"type":"error","name":"LastProposalIdTooLarge","inputs":[]},{"type":"error","name":"LengthExceedsUint16","inputs":[]},{"type":"error","name":"NoBlobs","inputs":[]},{"type":"error","name":"NotEnoughCapacity","inputs":[]},{"type":"error","name":"ParentBlockHashMismatch","inputs":[]},{"type":"error","name":"ProverNotWhitelisted","inputs":[]},{"type":"error","name":"REENTRANT_CALL","inputs":[]},{"type":"error","name":"UnprocessedForcedInclusionIsDue","inputs":[]},{"type":"error","name":"ZERO_ADDRESS","inputs":[]},{"type":"error","name":"ZERO_VALUE","inputs":[]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"BondInstructionCreated","inputs":[{"type":"uint48","name":"proposalId","internalType":"uint48","indexed":true},{"type":"tuple","name":"bondInstruction","internalType":"struct LibBonds.BondInstruction","indexed":false,"components":[{"type":"uint48","name":"proposalId","internalType":"uint48"},{"type":"uint8","name":"bondType","internalType":"enum LibBonds.BondType"},{"type":"address","name":"payer","internalType":"address"},{"type":"address","name":"payee","internalType":"address"}]}],"anonymous":false},{"type":"event","name":"DebugAddress","inputs":[{"type":"uint8","name":"index","internalType":"uint8","indexed":false},{"type":"address","name":"addr","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"DebugHash","inputs":[{"type":"uint8","name":"index","internalType":"uint8","indexed":false},{"type":"bytes32","name":"hash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"DebugNumber","inputs":[{"type":"uint8","name":"index","internalType":"uint8","indexed":false},{"type":"uint48","name":"number","internalType":"uint48","indexed":false}],"anonymous":false},{"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},{"type":"event","name":"InboxActivated","inputs":[{"type":"bytes32","name":"lastPacayaBlockHash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Proposed","inputs":[{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"Proved","inputs":[{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"activate","inputs":[{"type":"bytes32","name":"_lastPacayaBlockHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint48","name":"","internalType":"uint48"}],"name":"activationTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"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"}]}],"name":"getConfig","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","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"}]}],"name":"getCoreState","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"feeInGwei_","internalType":"uint64"}],"name":"getCurrentForcedInclusionFee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint48","name":"head_","internalType":"uint48"},{"type":"uint48","name":"tail_","internalType":"uint48"}],"name":"getForcedInclusionState","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"inclusions_","internalType":"struct IForcedInclusionStore.ForcedInclusion[]","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"}]}]}],"name":"getForcedInclusions","inputs":[{"type":"uint48","name":"_start","internalType":"uint48"},{"type":"uint48","name":"_maxCount","internalType":"uint48"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getProposalHash","inputs":[{"type":"uint256","name":"_proposalId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"impl","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"inNonReentrant","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"init","inputs":[{"type":"address","name":"_owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingOwner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"propose","inputs":[{"type":"bytes","name":"_lookahead","internalType":"bytes"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"prove","inputs":[{"type":"bytes","name":"_data","internalType":"bytes"},{"type":"bytes","name":"_proof","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"proxiableUUID","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"resolver","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"saveForcedInclusion","inputs":[{"type":"tuple","name":"_blobReference","internalType":"struct LibBlobs.BlobReference","components":[{"type":"uint16","name":"blobStartIndex","internalType":"uint16"},{"type":"uint16","name":"numBlobs","internalType":"uint16"},{"type":"uint24","name":"offset","internalType":"uint24"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]}]
Contract Creation Code
0x6102a080604052346104865760a0816148458038038091610020828561052d565b8339810103126104865761003381610550565b9061004060208201610550565b61004c60408301610550565b90610065608061005e60608601610550565b9401610550565b60405194906101e086016001600160401b038111878210176105195760409081526001600160a01b039182168752918116602087015291821690850152908116606084015216608080830191909152611c2060a083015260b460c0830152606460e0830152604b61010083015260016101208301525f6101408301819052629896806101608401526032610180808501919091526101a084015260056101c08401523090915254600881901c60ff166104c45760ff8082160361048a575b5073f88ef5437749a225621101be8c1be1a0ce9677583b1561048657604080516348ed17ff60e11b815282516001600160a01b03908116600483015260208401518116602483015291830151821660448201526060830151821660648201526080830151909116608482015260a082015165ffffffffffff90811660a483015260c08301511660c482015260e082015160e482015261010082015160ff90811661010483015261012083015161012483015261014083015161ffff9081166101448401526101608401516001600160401b03908116610164850152610180850151166101848401526101a0840151166101a48301526101c0830151166101c4820152905f826101e48173f88ef5437749a225621101be8c1be1a0ce9677585af490811561047b5760ff926101c09261046b575b5080516001600160a01b0390811660c09081526020830151821660e0908152604080850151841661010090815260608601518516610120908152608087015190951661014090815260a087015165ffffffffffff9081166101609081529588015116610180908152938701516101a09081529187015189168852948601516101e0529385015161ffff90811661020052928501516001600160401b0390811661022052918501519091166102405291830151166102605291015190911661028052516142e09081610565823960805181818161038a0152818161075c01526107af015260a05181610201015260c05181610ff5015260e05181818161101901526119490152610100518181816110480152612e7b01526101205181818161107701526130180152610140518181816110a6015281816119c6015261356b0152610160518181816110dc015261348001526101805181818161110a015261345c01526101a051818181611131015281816121a7015281816128fa015281816129590152612d1401526101c0518181816111590152612dcb01526101e0518181816111810152613b390152610200518181816111ab01528181613b930152613bcb0152610220518181816111db01528181611359015261146d01526102405181818161120b0152818161138101526114950152610260518181816112360152611adc0152610280518181816112600152613b6e0152f35b5f6104759161052d565b5f610256565b6040513d5f823e3d90fd5b5f80fd5b60ff90811916175f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a15f610123565b60405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b634e487b7160e01b5f52604160045260245ffd5b601f909101601f19168101906001600160401b0382119082101761051957604052565b51906001600160a01b03821682036104865756fe60806040526004361015610011575f80fd5b5f3560e01c80630423c7de146101b457806304f3bcec146101af57806319ab453c146101aa5780633075db56146101a55780633659cfe6146101a05780633f4ba83a1461019b57806340df9866146101965780634f1ef2861461019157806352d1902d1461018c57806359db6e85146101875780635c975abb146101825780635ccc17181461017d5780636aa6a01a14610178578063715018a61461017357806379ba50971461016e5780638456cb59146101695780638abf6077146101645780638da5cb5b1461015f5780639791e6441461015a578063a834725a14610155578063c3f909d414610150578063df596d9e1461014b578063e305333514610146578063e30c397814610141578063ea1917431461013c5763f2fde38b14610137575f80fd5b611b3b565b61155a565b611532565b61143f565b6112c1565b610fc7565b610e8e565b610c95565b610bf0565b610bbc565b610b50565b610acc565b610a67565b6109e1565b6109b1565b610983565b610865565b61079d565b61070a565b610493565b610418565b610368565b610339565b610241565b6101ec565b6101c7565b5f9103126101c357565b5f80fd5b346101c3575f3660031901126101c357602065ffffffffffff60fb5416604051908152f35b346101c3575f3660031901126101c3576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6001600160a01b038116036101c357565b346101c35760203660031901126101c35760043561025e81610230565b6102ac5f549161029261027c6102788560ff9060081c1690565b1590565b8094819561032b575b811561030b575b50611bab565b826102a3600160ff195f5416175f55565b6102f4576123c6565b6102b257005b6102c05f5461ff0019165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1005b6103066101005f5461ff001916175f55565b6123c6565b303b1591508161031d575b505f61028c565b60ff1660011490505f610316565b600160ff8216109150610285565b346101c3575f3660031901126101c3576020600260ff5f51602061426b5f395f51905f525c1614604051908152f35b346101c35760203660031901126101c35760043561038581610230565b6103dc7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166103be30821415611c0e565b5f51602061428b5f395f51905f52546001600160a01b031614611c6f565b6103e46128a0565b604051610411916103f660208361063b565b5f8252601f196104055f6106b9565b013660208401376124be565b005b61059f565b346101c3575f3660031901126101c35761044261043d600260ff60c95460081c161490565b612646565b61010060c95461ff0019161760c9557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a16104116128a0565b65ffffffffffff8116036101c357565b346101c35760403660031901126101c3576104c56004356104b381610483565b602435906104c082610483565b6127d6565b6040518091602082016020835281518091526040830190602060408260051b8601019301915f905b8282106104fc57505050500390f35b919390929450603f19868203018252602085516001600160401b0381511683520151906040602082015260a0810191805192606060408401528351809152602060c084019401905f905b80821061058757505050600192602092608065ffffffffffff60408562ffffff888098015116606086015201511691015296019201920185949391926104ed565b90919460208060019288518152019601920190610546565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b0382111761041357604052565b608081019081106001600160401b0382111761041357604052565b604081019081106001600160401b0382111761041357604052565b60c081019081106001600160401b0382111761041357604052565b6101e081019081106001600160401b0382111761041357604052565b90601f801991011681019081106001600160401b0382111761041357604052565b6040519061066c6101e08361063b565b565b6040519061066c60608361063b565b6040519061066c60208361063b565b6040519061066c60408361063b565b6040519061066c60808361063b565b6040519061066c60c08361063b565b6001600160401b03811161041357601f01601f191660200190565b9291926106e0826106b9565b916106ee604051938461063b565b8294818452818301116101c3578281602093845f960137010152565b60403660031901126101c35760043561072281610230565b602435906001600160401b0382116101c357366023830112156101c3576107566104119236906024816004013591016106d4565b906107907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166103be30821415611c0e565b6107986128a0565b612586565b346101c3575f3660031901126101c3577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036107fa576040515f51602061428b5f395f51905f52815280602081015b0390f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b346101c35760203660031901126101c3576004356108816128a0565b65ffffffffffff60fb541660405190633dd0723360e21b825282600483015260248201525f8160448173f88ef5437749a225621101be8c1be1a0ce9677585af491821561097e576109376102ef927fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d2945f5f915f925f925f92610947575b610932939495509061092861092d9265ffffffffffff1665ffffffffffff1960fb54161760fb55565b612048565b6128f8565b61298d565b6040519081529081906020820190565b505050505061092d610932610970610928933d805f833e610968818361063b565b810190611f6e565b9196508695509350916108ff565b61203d565b346101c3575f3660031901126101c35760206109a7600260ff60c95460081c161490565b6040519015158152f35b346101c3575f3660031901126101c35760406101005465ffffffffffff825191818116835260301c166020820152f35b346101c3575f3660031901126101c3576109f96120db565b5060c0610a0461210b565b60a06040519165ffffffffffff815116835265ffffffffffff602082015116602084015265ffffffffffff604082015116604084015265ffffffffffff606082015116606084015265ffffffffffff6080820151166080840152015160a0820152f35b346101c3575f3660031901126101c357610a7f6128a0565b606580546001600160a01b03199081169091556033805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346101c3575f3660031901126101c357606554336001600160a01b0390911603610af95761041133612bc0565b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b346101c3575f3660031901126101c357610b7b610b75600260ff60c95460081c161490565b15612646565b61020060c95461ff0019161760c9557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a16104116128a0565b346101c3575f3660031901126101c3575f51602061428b5f395f51905f52546040516001600160a01b039091168152602090f35b346101c3575f3660031901126101c3576033546040516001600160a01b039091168152602090f35b9181601f840112156101c3578235916001600160401b0383116101c357602083818601950101116101c357565b60406003198201126101c3576004356001600160401b0381116101c35781610c6f91600401610c18565b92909291602435906001600160401b0382116101c357610c9191600401610c18565b9091565b346101c357610ca336610c45565b600260ff5f51602061426b5f395f51905f529493945c1614610e7f5765ffffffffffff610e0e6026610e7796610dc35f610dbb6040610dae610cfd60019c610e2d9b60025f51602061426b5f395f51905f525d36916106d4565b610d9f610d92610d82610d75610d6887519c8d96610d1a886105b3565b8b8852610d5a60208901988b51610d30816105b3565b8e81528e60208201528e8d8201528a528b81019d8e52602083015160d01c65ffffffffffff169052565b01906002825160f01c920190565b919086519061ffff169052565b906002825160f01c920190565b919060208551019061ffff169052565b906003825160e81c920190565b93909151019062ffffff169052565b906001825160f81c920190565b5060ff169052565b610dcc82612c13565b60fc549065ffffffffffff8216968791610dfb603085901c65ffffffffffff169460601c65ffffffffffff1690565b94610e09888516151561216d565b612ccf565b949093011665ffffffffffff1665ffffffffffff1960fc54161760fc55565b60fc80546bffffffffffff00000000000019164360301b6bffffffffffff00000000000016179055610932610e68825165ffffffffffff1690565b610e7183612ee8565b9061294c565b610411613a8a565b63dfc60d8560e01b5f5260045ffd5b346101c35760203660031901126101c3576020610eac6004356121a1565b604051908152f35b81516001600160a01b031681526101e08101929161066c91906101c09081906020818101516001600160a01b0316908501526040818101516001600160a01b0316908501526060818101516001600160a01b0316908501526080818101516001600160a01b03169085015260a08181015165ffffffffffff169085015260c08181015165ffffffffffff169085015260e081015160e0850152610f6361010082015161010086019060ff169052565b610120810151610120850152610f8661014082015161014086019061ffff169052565b610160818101516001600160401b031690850152610180818101516001600160401b0316908501526101a08181015161ffff1690850152015160ff16910152565b346101c3575f3660031901126101c357610fdf6121db565b506107f6610feb61065c565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001681527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660408201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660608201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316608082015265ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660a082015265ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660c08201527f000000000000000000000000000000000000000000000000000000000000000060e082015260ff7f0000000000000000000000000000000000000000000000000000000000000000166101008201527f000000000000000000000000000000000000000000000000000000000000000061012082015261ffff7f0000000000000000000000000000000000000000000000000000000000000000166101408201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000166101608201526001600160401b037f00000000000000000000000000000000000000000000000000000000000000001661018082015261ffff7f0000000000000000000000000000000000000000000000000000000000000000166101a082015260ff7f0000000000000000000000000000000000000000000000000000000000000000166101c082015260405191829182610eb4565b6004359061ffff821682036101c357565b6024359061ffff821682036101c357565b62ffffff8116036101c357565b60603660031901126101c3576113d760206040516112de816105b3565b6112e6611292565b81526112f06112a3565b82820152604435611300816112b4565b604082015260015f5260fe60205261133a7f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b7541515612248565b604080516312b2aa9160e31b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000166044820152825161ffff9081166064830152602084015116608482015291015162ffffff1660a4820152918290819060c4820190565b038173d1a27f331c17ed8cbb6dabce67a42d6b8a6b0e145af490811561097e575f91611410575b508061140657005b6104119033612fde565b611432915060203d602011611438575b61142a818361063b565b81019061225e565b5f6113fe565b503d611420565b346101c3575f3660031901126101c3576040516343c3d71960e01b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f000000000000000000000000000000000000000000000000000000000000000016604482015260208160648173d1a27f331c17ed8cbb6dabce67a42d6b8a6b0e145af4801561097e576107f6915f91611503575b506040516001600160401b0390911681529081906020820190565b611525915060203d60201161152b575b61151d818361063b565b81019061226d565b5f6114e8565b503d611513565b346101c3575f3660031901126101c3576065546040516001600160a01b039091168152602090f35b346101c35761156836610c45565b9261158e61158961157833613016565b9261158161210b565b9536916106d4565b61319e565b9283519361159c85836132f4565b9290919365ffffffffffff84169283155f14611b16576020890151945b6115c960a08401968751146122c6565b60408a01976115e289516115dc856121a1565b146122dc565b15611b06575b50602083015115158015611abc575b6119bf575b65ffffffffffff16604082015265ffffffffffff4216606082019081529360c08901958651905f190161162e916122b2565b5160600151905261163e90612048565b61164661067d565b90815261165290613612565b604051611660819282612316565b037fb2d5049ba96efb9e1fee66a51e4e6cbdfa2949627891ee29c6e4281abb8da03c91a1825190611690916122b2565b516040015190516116ac9165ffffffffffff918216911661374f565b4203936116b881613761565b92604051806116d38682919060206040840193600181520152565b035f51602061424b5f395f51905f5291a18151604080516002815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a1602082015160405161173f819282919060206040840193600381520152565b035f51602061424b5f395f51905f5291a15160405161176b819282919060206040840193600481520152565b035f51602061424b5f395f51905f5291a1606081015160408051600581526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a16080810151604080516006815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a160a00151604051611819819282919060206040840193600781520152565b035f51602061424b5f395f51905f5291a18051611835906122a0565b5160600151604051611854819282919060206040840193600881520152565b035f51602061424b5f395f51905f5291a18051611870906122a0565b515160408051600981526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a180516118b8906122a0565b5160209081015160408051600a81526001600160a01b03909216928201929092527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba9190a151611907906122a0565b516040908101518151600b815265ffffffffffff90911660208201527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b147749190a17f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b156101c3575f9361199b604051968795869485946314bcf3dd60e01b86526004860161234a565b03915afa801561097e576119ab57005b806119b95f6104119361063b565b806101b9565b60808901517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316919065ffffffffffff16918a6060611a1360c060a08401519301515f198c01906122b2565b510151611a2f611a2161066e565b65ffffffffffff9096168652565b60208501526040840152803b156101c35760408051631934171960e31b8152845165ffffffffffff1660048201526020850151602482015293015160448401525f908390606490829084905af191821561097e5765ffffffffffff92611aa8575b5065ffffffffffff42831616608084015290506115fc565b806119b95f611ab69361063b565b5f611a90565b5065ffffffffffff611ad7608084015165ffffffffffff1690565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001601164210156115f7565b611b10908a61340c565b5f6115e8565b6060611b3260c08b015165ffffffffffff5f19890116906122b2565b510151946115b9565b346101c35760203660031901126101c357600435611b5881610230565b611b606128a0565b606580546001600160a01b0319166001600160a01b039283169081179091556033549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b15611bb257565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b15611c1557565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b15611c7657565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b90611cda826106b9565b611ce7604051918261063b565b8281528092611cf8601f19916106b9565b0190602036910137565b519061066c82610483565b6001600160401b0381116104135760051b60200190565b519081151582036101c357565b519061066c826112b4565b91906080838203126101c357604051611d54816105ce565b80938051611d6181610483565b825260208101516020830152604081015160ff811681036101c35760408301526060810151906001600160401b0382116101c357019180601f840112156101c3578251611dad81611d0d565b93611dbb604051958661063b565b81855260208086019260051b820101908382116101c35760208101925b828410611dea57505050505060600152565b83516001600160401b0381116101c35782016040818703601f1901126101c35760405190611e17826105e9565b611e2360208201611d24565b825260408101516001600160401b0381116101c35760209101016060818803126101c35760405190611e54826105b3565b80516001600160401b0381116101c357810188601f820112156101c357805190611e7d82611d0d565b91611e8b604051938461063b565b80835260208084019160051b830101918b83116101c357602001905b828210611eea5750505091611ed6604060209694938796948452611ecc878201611d31565b8785015201611d02565b604082015283820152815201930192611dd8565b8151815260209182019101611ea7565b91908260c09103126101c357604051611f1281610604565b60a08082948051611f2281610483565b84526020810151611f3281610483565b60208501526040810151611f4581610483565b60408501526060810151611f5881610230565b6060850152608081015160808501520151910152565b9190828103926101e084126101c35760c08151611f8a81610483565b94601f1901126101c357604051611fa081610604565b6020820151611fae81610483565b81526040820151611fbe81610483565b60208201526060820151611fd181610483565b60408201526080820151611fe481610483565b606082015260a0820151611ff781610483565b608082015260c082015160a08201529260e08201516001600160401b0381116101c35761203761202c856101c0938601611d3c565b946101008501611efa565b92015190565b6040513d5f823e3d90fd5b805160fc805460208401516040850151606080870151608088015165ffffffffffff60c01b60c09190911b166001600160f01b031990951665ffffffffffff909716969096176bffffffffffff00000000000060309490941b9390931692909217911b65ffffffffffff60601b161760909390931b65ffffffffffff60901b169290921791909117905560a0015160fd55565b604051906120e882610604565b5f60a0838281528260208201528260408201528260608201528260808201520152565b6040519061211882610604565b8161216365ffffffffffff60fc548181168452818160301c166020850152818160601c16604085015281808260901c1616606085015260c01c16608083019065ffffffffffff169052565b60a060fd54910152565b1561217457565b63ba74d80f60e01b5f5260045ffd5b811561218d570690565b634e487b7160e01b5f52601260045260245ffd5b6121cc907f000000000000000000000000000000000000000000000000000000000000000090612183565b5f5260fe60205260405f205490565b604051906121e88261061f565b5f6101c0838281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a08201520152565b1561224f57565b63f37a8b1360e01b5f5260045ffd5b908160209103126101c3575190565b908160209103126101c357516001600160401b03811681036101c35790565b634e487b7160e01b5f52603260045260245ffd5b8051156122ad5760200190565b61228c565b80518210156122ad5760209160051b010190565b156122cd57565b63198070b360e01b5f5260045ffd5b156122e357565b63f904c2fd60e01b5f5260045ffd5b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9060206123279281815201906122f2565b90565b908060209392818452848401375f828201840152601f01601f1916010190565b612327949260609282526020820152816040820152019161232a565b1561236d57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b6123df60ff5f5460081c166123da81612366565b612366565b6001600160a01b03811661240857506123f733612bc0565b61010060c95461ff0019161760c955565b6123f790612bc0565b1561241857565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b906124ea7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b156124f9575061066c906139e2565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281612565575b506125435760405162461bcd60e51b81528061253f6004820161246f565b0390fd5b61066c926125605f51602061428b5f395f51905f525f9414612411565b613900565b61257f91935060203d6020116114385761142a818361063b565b915f612521565b906125b27f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b156125c1575061066c906139e2565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281612625575b506126075760405162461bcd60e51b81528061253f6004820161246f565b61066c926125605f51602061428b5f395f51905f5260019414612411565b61263f91935060203d6020116114385761142a818361063b565b915f6125e9565b1561264d57565b63bae6e2a960e01b5f5260045ffd5b60405190612669826105b3565b5f604083606081528260208201520152565b60405190612688826105e9565b815f8152602061269661265c565b910152565b604051906126aa60208361063b565b5f80835282815b8281106126bd57505050565b6020906126c861267b565b828285010152016126b1565b906126de82611d0d565b6126eb604051918261063b565b82815280926126fc601f1991611d0d565b01905f5b82811061270c57505050565b60209061271761267b565b82828501015201612700565b90604051612730816105b3565b80926040518060208354918281520190835f5260205f20905f5b81811061279757505050600161066c94938361276d60409561278a95038261063b565b8552015462ffffff8116602085015260181c65ffffffffffff1690565b65ffffffffffff16910152565b825484526020909301926001928301920161274a565b906040516127ba816105e9565b6020612696600183956001600160401b03815416855201612723565b6101005465ffffffffffff8281169493603083901c821693929091168510801561288e575b801561287e575b6128715761281d929165ffffffffffff809216920316613a7e565b612826816126d4565b925f5b82811061283557505050565b80612855612850846001940160ff905f5260205260405f2090565b6127ad565b61285f82886122b2565b5261286a81876122b2565b5001612829565b505050905061232761269b565b5065ffffffffffff811615612802565b5065ffffffffffff83168510156127fb565b6033546001600160a01b031633036128b457565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b7f0000000000000000000000000000000000000000000000000000000000000000801561218d57505f805260fe6020527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af55565b61297f9065ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000009116612183565b5f5260fe60205260405f2055565b906040519161299b836105e9565b82526129b96129b460606020850193808552015161402f565b611cd0565b91612a6f612a60612a52612a42612a34612a21612a0e6129f360208b016129e88a5165ffffffffffff90511690565b60d01b815260060190565b8851606001516001600160a01b03165b60601b815260140190565b87516020015165ffffffffffff166129e8565b86516040015165ffffffffffff166129e8565b855160800151815260200190565b85515165ffffffffffff166129e8565b845160209081015182520190565b83516040015160ff1690614026565b91612a9b6060825101515193612a848561400d565b6001600160f01b031960f086901b16815260020190565b925f915b818310612ae8575050905160a00151909152506040517f10b2060c55406ea48522476f67fd813d4984b12078555d3e2a377e35839d7d01918190612ae39082612316565b0390a1565b9091936020612b18612aff876060865101516122b2565b5192612b0b8451151590565b15612bb957600190614026565b910190612b438251515191612b2c8361400d565b6001600160f01b031960f084901b16815260020190565b905f905b808210612b94575050816129e86040612b7c612b8b94612b716020600198510162ffffff90511690565b60e81b815260030190565b9251015165ffffffffffff1690565b94019190612a9f565b9091612bb1600191612ba8858751516122b2565b51815260200190565b920190612b47565b5f90614026565b606580546001600160a01b0319908116909155603380549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b5165ffffffffffff168015908115612c3d575b5015612c2e57565b63559895a360e01b5f5260045ffd5b90504211155f612c26565b60405190612c55826105ce565b606080835f81525f60208201525f60408201520152565b15612c7357565b6349517a1d60e11b5f5260045ffd5b15612c8957565b63eaabac9b60e01b5f5260045ffd5b908160209103126101c3575161232781610483565b6001600160a01b0390911681526040602082018190526123279391019161232a565b94612d3890612cff65ffffffffffff612d3f94959697612ced6120db565b50612cf6612c48565b50164311612c6c565b5f1965ffffffffffff918703821681019091167f0000000000000000000000000000000000000000000000000000000000000000030190565b1515612c82565b612d98612d6f6020612d67612d61612d5b60408a015160ff1690565b60ff1690565b33613acc565b960151613c84565b612d7761068c565b905f8252602082015285515f1981510191612d9283836122b2565b526122b2565b50602084015115612e525750505f5b5f1943019251612db561069b565b65ffffffffffff851681529340602085015260ff7f0000000000000000000000000000000000000000000000000000000000000000166040850152606084015282612e3f612e16612e105f19860165ffffffffffff166121a1565b92613d6d565b92612e22611a216106aa565b4265ffffffffffff16602086015265ffffffffffff166040850152565b336060840152608083015260a082015291565b604051635600026d60e11b81529160209183918291612e7691903360048501612cad565b03815f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af190811561097e575f91612eb9575b50612da7565b612edb915060203d602011612ee1575b612ed3818361063b565b810190612c98565b5f612eb3565b503d612ec9565b612fb560a060405192600684528360e001604052612f26612f1d612f12835165ffffffffffff1690565b65ffffffffffff1690565b60208601528490565b50612f49612f40612f12602084015165ffffffffffff1690565b60408601528490565b50612f6c612f63612f12604084015165ffffffffffff1690565b60608601528490565b506060810151612f9f90612f9690612f8a906001600160a01b031681565b6001600160a01b031690565b60808601528490565b50608081015160a0850152015160c08301528190565b50805160051b6020820120612327905b918051604051828260010160051b011490151060061b52565b61066c915a91613f61565b91908260409103126101c357602061203783611d24565b1561300757565b63c1a58f1960e01b5f5260045ffd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169081156130c95760408051633326844b60e11b81526001600160a01b0390921660048301529091829060249082905afa801561097e575f915f91613098575b50156130935761308e90613000565b600190565b505f90565b90506130bc915060403d6040116130c2575b6130b4818361063b565b810190612fe9565b5f61307f565b503d6130aa565b50505f90565b604051906130dc826105e9565b60405160e08101836001600160401b03821183831017610413575f9260209260405283815283838201528360408201528360608201528360808201528360a0820152606060c082015281520152565b60405190613138826105ce565b5f6060838281528260208201528260408201520152565b9061315982611d0d565b613166604051918261063b565b8281528092613177601f1991611d0d565b01905f5b82811061318757505050565b60209061319261312b565b8282850101520161317b565b9061ffff61326261324e6131ea61323a61322d6132196132056131f46131ea6131d960206131ca6130cf565b9d01906006825160d01c920190565b91908d519065ffffffffffff169052565b9060208251920190565b9060208c5101529060208251920190565b9060408b510152906014825160601c920190565b919060608a51019060018060a01b03169052565b906006825160d01c920190565b919060808851019065ffffffffffff169052565b9060a086510152906002825160f01c920190565b911661326d8161314f565b60c0855101525f905b80821061328c5750505160f81c15156020830152565b9091613299600191613fa9565b93906132aa8260c0895101516122b2565b520190613276565b156132b957565b6363db3a4160e01b5f5260045ffd5b156132cf57565b63677c56f160e01b5f5260045ffd5b156132e557565b63181432e760e11b5f5260045ffd5b909165ffffffffffff60018160408501511601169260c08101515193841561339d57613390612f12836133438465ffffffffffff61333b612327985165ffffffffffff1690565b1611156132b2565b613378613371612f125f198b613362612f12875165ffffffffffff1690565b0101995165ffffffffffff1690565b88106132c8565b613384848810156132de565b5165ffffffffffff1690565b900365ffffffffffff1690565b63c2e5347d60e01b5f5260045ffd5b815165ffffffffffff168152602082015160808201939260028210156133f85760208301919091526040818101516001600160a01b039081169184019190915260609182015116910152565b634e487b7160e01b5f52602160045260245ffd5b9060c082019182516134a661343d604061342f65ffffffffffff871680956122b2565b51015165ffffffffffff1690565b65ffffffffffff8061345a60fc5465ffffffffffff9060901c1690565b7f00000000000000000000000000000000000000000000000000000000000000000116917f0000000000000000000000000000000000000000000000000000000000000000011661374f565b42111561360c5761350660606134f760206134e8613529956134e1613539996134d58a5165ffffffffffff1690565b0165ffffffffffff1690565b99516122b2565b5101516001600160a01b031690565b9301516001600160a01b031690565b91613512611a2161069b565b600160208601526001600160a01b03166040850152565b6001600160a01b03166060830152565b613566602061354783613fe4565b6040518093819263019b28af60e61b8352600483019190602083019252565b03815f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1801561097e576135ef575b507f8796b99bbf275a983988181e85b42502d9347327f4dde674320bec3879bcc5e16135ea65ffffffffffff6135dc845165ffffffffffff1690565b1692604051918291826133ac565b0390a2565b6136079060203d6020116114385761142a818361063b565b6135a0565b50505050565b908151519060c08201916136c06136a36136346129b4865151604e0260830190565b9260a061369861368661367361366661365a60208a016129e8885165ffffffffffff1690565b60208781015182520190565b6040860151815260200190565b60608501516001600160a01b0316612a03565b608084015165ffffffffffff166129e8565b910151815260200190565b6136ae85515161400d565b84515161ffff1660f01b815260020190565b915f925b84518051851015613733576001916136df8661372b936122b2565b518051606090811b6bffffffffffffffffffffffff1990811684526020830151821b166014840152604082015160d01b6001600160d01b03191660288401520151602e820152604e0190565b9301926136c4565b509194612b0b91945061374c9350602090510151151590565b50565b908082111561375c575090565b905090565b60c081015180519061381d60a061378d8460021b60090190604051828193825260010160051b01604052565b602080820152946137b36137aa612f12835165ffffffffffff1690565b60408801528690565b50602081015160608701526040810151608087015260608101516137ee906137e590612f8a906001600160a01b031681565b60a08801528690565b50613811613808612f12608084015165ffffffffffff1690565b60c08801528690565b50015160e08501528390565b5060e061010084015261012083018290525f9060095b8383106138525750505050612327612fc5826020815160051b91012090565b60046001916138f6606061386687876122b2565b51805161388f9061388190612f8a906001600160a01b031681565b6001860160051b8c01528a90565b5060208101516138bd906138ad90612f8a906001600160a01b031681565b60018689010160051b8c01528a90565b506138e56138d7612f12604084015165ffffffffffff1690565b6003860160051b8c01528a90565b5001516004830160051b8901528790565b5001920191613833565b9161390a836139e2565b6001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2815115908115916139da575b5061394d575050565b61374c915f806040519361396260608661063b565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020860152660819985a5b195960ca1b6040860152602081519101845af43d156139d2573d916139b6836106b9565b926139c4604051948561063b565b83523d5f602085013e6141b1565b6060916141b1565b90505f613944565b803b15613a235760018060a01b03166bffffffffffffffffffffffff60a01b5f51602061428b5f395f51905f525416175f51602061428b5f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b8181111561375c575090565b60015f51602061426b5f395f51905f525d565b60405190613aaa826105e9565b5f602083606081520152565b15613abd57565b63014b3fdb60e11b5f5260045ffd5b919065ffffffffffff61066c91613ae1613a9d565b9461010054613b07613af88265ffffffffffff1690565b9160301c65ffffffffffff1690565b91613b348583850316918286115f14613c0657829384915b613b2b600184016126d4565b90818d52614066565b9290947f0000000000000000000000000000000000000000000000000000000000000000119182613bfc575b5050613bbe575b50501660ff7f00000000000000000000000000000000000000000000000000000000000000001661ffff7f000000000000000000000000000000000000000000000000000000000000000016020142116020840152565b610278613bf091613bf5937f000000000000000000000000000000000000000000000000000000000000000091614173565b613ab6565b5f80613b67565b1190505f80613b60565b85938491613b1f565b15613c1657565b63fdac229f60e01b5f5260045ffd5b90613c2f82611d0d565b613c3c604051918261063b565b8281528092611cf8601f1991611d0d565b91908201809211613c5a57565b634e487b7160e01b5f52601160045260245ffd5b15613c7557565b637bb2fa2f60e11b5f5260045ffd5b90613c8d61265c565b506020820191613cad61ffff613ca5855161ffff1690565b161515613c0f565b613ccb613cc6613cbf855161ffff1690565b61ffff1690565b613c25565b915f5b613cdd613cbf865161ffff1690565b811015613d2f57613cbf600182613d05613cdd94613d00613cbf895161ffff1690565b613c4d565b49613d1082896122b2565b52613d26613d1e82896122b2565b511515613c6e565b01915050613cce565b509250613d456040613d5c92015162ffffff1690565b613d4d61066e565b92835262ffffff166020830152565b4265ffffffffffff16604082015290565b606081015180519081600601805f5b848110613f2b5750612f96612d5b6040613da8613de19490604051828193825260010160051b01604052565b60208082015297613dce613dc5612f12835165ffffffffffff1690565b60408b01528990565b50602081015160608a0152015160ff1690565b50608060a085015260c08401839052905f915b838310613e135750505050612327612fc5826020815160051b91012090565b6020613e1f84846122b2565b51613e39600519840160051b6007870160051b8901528790565b50805115613f2057613e5860ff60015b166001850160051b8901528790565b5060406002840160051b88015260606003840160051b88015201613ea0613e92613e8a602084510162ffffff90511690565b62ffffff1690565b6004840160051b8801528690565b50613eca613ebc612f12604084510165ffffffffffff90511690565b6005808501901b8801528690565b50515180516006830160051b870181905291905f5b838110613ef85750506001916006910101920191613df4565b80613f19613f08600193856122b2565b5160078684010160051b8b01528990565b5001613edf565b613e5860ff5f613e49565b9060066001916020613f3d85886122b2565b510151515101019101613d7c565b15613f5257565b634c67134d60e11b5f5260045ffd5b91908015613fa45761066c925f92839260405192613f8060208561063b565b848452613f976001600160a01b0382161515613f4b565b60208451940192f1613f4b565b505050565b613fb161312b565b91815160601c8352601482015160601c6020840152602882015160d01c6040840152604e602e8301519201916060840152565b60405161400781613ff96020820194856133ac565b03601f19810183528261063b565b51902090565b61ffff1061401757565b63161e7a6b60e11b5f5260045ffd5b60019181530190565b5f9190608f5b815184101561406157600c600191602061404f87866122b2565b510151515160051b0101930192614035565b925050565b9392938415614164575f905f5b8681106140ea57506040602061409e65ffffffffffff9695856140ae9589976140d3575b50506122a0565b510151015165ffffffffffff1690565b941601169061066c826101009065ffffffffffff1665ffffffffffff19825416179055565b633b9aca006140e3920290612fde565b5f80614097565b9160019061415c6141506141118665ffffffffffff8a160160ff905f5260205260405f2090565b61411961068c565b60018152614128868301612723565b6020820152614137888a6122b2565b5261414287896122b2565b50546001600160401b031690565b6001600160401b031690565b019201614073565b5050915065ffffffffffff9190565b65ffffffffffff809116911681146130c9575f5260ff60205265ffffffffffff600260405f20015460181c169081156130c95761ffff160142101590565b9192901561421357508151156141c5575090565b3b156141ce5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156142265750805190602001fd5b60405162461bcd60e51b81526020600482015290819061253f9060248301906122f256fe712de588b76f7fdb47439ab8677a0c8233392168ef0308d402c7b8d72138a080a5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220664da4c6aa12e8168ded1ddf7dcf200d84f7ca508d47d95178e7b1a107f3eafb64736f6c634300081e00330000000000000000000000009d1313add47c8b69882d6a4605df112fc501f341000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e0000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb3254426400000000000000000000000000acc4d239aa05c797e038b7701be8be6940143900000000000000000000000012100faa7b157e9947340b44409fc7e27ec0abef
Deployed ByteCode
0x60806040526004361015610011575f80fd5b5f3560e01c80630423c7de146101b457806304f3bcec146101af57806319ab453c146101aa5780633075db56146101a55780633659cfe6146101a05780633f4ba83a1461019b57806340df9866146101965780634f1ef2861461019157806352d1902d1461018c57806359db6e85146101875780635c975abb146101825780635ccc17181461017d5780636aa6a01a14610178578063715018a61461017357806379ba50971461016e5780638456cb59146101695780638abf6077146101645780638da5cb5b1461015f5780639791e6441461015a578063a834725a14610155578063c3f909d414610150578063df596d9e1461014b578063e305333514610146578063e30c397814610141578063ea1917431461013c5763f2fde38b14610137575f80fd5b611b3b565b61155a565b611532565b61143f565b6112c1565b610fc7565b610e8e565b610c95565b610bf0565b610bbc565b610b50565b610acc565b610a67565b6109e1565b6109b1565b610983565b610865565b61079d565b61070a565b610493565b610418565b610368565b610339565b610241565b6101ec565b6101c7565b5f9103126101c357565b5f80fd5b346101c3575f3660031901126101c357602065ffffffffffff60fb5416604051908152f35b346101c3575f3660031901126101c3576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6001600160a01b038116036101c357565b346101c35760203660031901126101c35760043561025e81610230565b6102ac5f549161029261027c6102788560ff9060081c1690565b1590565b8094819561032b575b811561030b575b50611bab565b826102a3600160ff195f5416175f55565b6102f4576123c6565b6102b257005b6102c05f5461ff0019165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1005b6103066101005f5461ff001916175f55565b6123c6565b303b1591508161031d575b505f61028c565b60ff1660011490505f610316565b600160ff8216109150610285565b346101c3575f3660031901126101c3576020600260ff5f51602061426b5f395f51905f525c1614604051908152f35b346101c35760203660031901126101c35760043561038581610230565b6103dc7f0000000000000000000000000d272c6c9099330a0229fe0954973506416277e96001600160a01b03166103be30821415611c0e565b5f51602061428b5f395f51905f52546001600160a01b031614611c6f565b6103e46128a0565b604051610411916103f660208361063b565b5f8252601f196104055f6106b9565b013660208401376124be565b005b61059f565b346101c3575f3660031901126101c35761044261043d600260ff60c95460081c161490565b612646565b61010060c95461ff0019161760c9557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a16104116128a0565b65ffffffffffff8116036101c357565b346101c35760403660031901126101c3576104c56004356104b381610483565b602435906104c082610483565b6127d6565b6040518091602082016020835281518091526040830190602060408260051b8601019301915f905b8282106104fc57505050500390f35b919390929450603f19868203018252602085516001600160401b0381511683520151906040602082015260a0810191805192606060408401528351809152602060c084019401905f905b80821061058757505050600192602092608065ffffffffffff60408562ffffff888098015116606086015201511691015296019201920185949391926104ed565b90919460208060019288518152019601920190610546565b634e487b7160e01b5f52604160045260245ffd5b606081019081106001600160401b0382111761041357604052565b608081019081106001600160401b0382111761041357604052565b604081019081106001600160401b0382111761041357604052565b60c081019081106001600160401b0382111761041357604052565b6101e081019081106001600160401b0382111761041357604052565b90601f801991011681019081106001600160401b0382111761041357604052565b6040519061066c6101e08361063b565b565b6040519061066c60608361063b565b6040519061066c60208361063b565b6040519061066c60408361063b565b6040519061066c60808361063b565b6040519061066c60c08361063b565b6001600160401b03811161041357601f01601f191660200190565b9291926106e0826106b9565b916106ee604051938461063b565b8294818452818301116101c3578281602093845f960137010152565b60403660031901126101c35760043561072281610230565b602435906001600160401b0382116101c357366023830112156101c3576107566104119236906024816004013591016106d4565b906107907f0000000000000000000000000d272c6c9099330a0229fe0954973506416277e96001600160a01b03166103be30821415611c0e565b6107986128a0565b612586565b346101c3575f3660031901126101c3577f0000000000000000000000000d272c6c9099330a0229fe0954973506416277e96001600160a01b031630036107fa576040515f51602061428b5f395f51905f52815280602081015b0390f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b346101c35760203660031901126101c3576004356108816128a0565b65ffffffffffff60fb541660405190633dd0723360e21b825282600483015260248201525f8160448173f88ef5437749a225621101be8c1be1a0ce9677585af491821561097e576109376102ef927fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d2945f5f915f925f925f92610947575b610932939495509061092861092d9265ffffffffffff1665ffffffffffff1960fb54161760fb55565b612048565b6128f8565b61298d565b6040519081529081906020820190565b505050505061092d610932610970610928933d805f833e610968818361063b565b810190611f6e565b9196508695509350916108ff565b61203d565b346101c3575f3660031901126101c35760206109a7600260ff60c95460081c161490565b6040519015158152f35b346101c3575f3660031901126101c35760406101005465ffffffffffff825191818116835260301c166020820152f35b346101c3575f3660031901126101c3576109f96120db565b5060c0610a0461210b565b60a06040519165ffffffffffff815116835265ffffffffffff602082015116602084015265ffffffffffff604082015116604084015265ffffffffffff606082015116606084015265ffffffffffff6080820151166080840152015160a0820152f35b346101c3575f3660031901126101c357610a7f6128a0565b606580546001600160a01b03199081169091556033805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346101c3575f3660031901126101c357606554336001600160a01b0390911603610af95761041133612bc0565b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b346101c3575f3660031901126101c357610b7b610b75600260ff60c95460081c161490565b15612646565b61020060c95461ff0019161760c9557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a16104116128a0565b346101c3575f3660031901126101c3575f51602061428b5f395f51905f52546040516001600160a01b039091168152602090f35b346101c3575f3660031901126101c3576033546040516001600160a01b039091168152602090f35b9181601f840112156101c3578235916001600160401b0383116101c357602083818601950101116101c357565b60406003198201126101c3576004356001600160401b0381116101c35781610c6f91600401610c18565b92909291602435906001600160401b0382116101c357610c9191600401610c18565b9091565b346101c357610ca336610c45565b600260ff5f51602061426b5f395f51905f529493945c1614610e7f5765ffffffffffff610e0e6026610e7796610dc35f610dbb6040610dae610cfd60019c610e2d9b60025f51602061426b5f395f51905f525d36916106d4565b610d9f610d92610d82610d75610d6887519c8d96610d1a886105b3565b8b8852610d5a60208901988b51610d30816105b3565b8e81528e60208201528e8d8201528a528b81019d8e52602083015160d01c65ffffffffffff169052565b01906002825160f01c920190565b919086519061ffff169052565b906002825160f01c920190565b919060208551019061ffff169052565b906003825160e81c920190565b93909151019062ffffff169052565b906001825160f81c920190565b5060ff169052565b610dcc82612c13565b60fc549065ffffffffffff8216968791610dfb603085901c65ffffffffffff169460601c65ffffffffffff1690565b94610e09888516151561216d565b612ccf565b949093011665ffffffffffff1665ffffffffffff1960fc54161760fc55565b60fc80546bffffffffffff00000000000019164360301b6bffffffffffff00000000000016179055610932610e68825165ffffffffffff1690565b610e7183612ee8565b9061294c565b610411613a8a565b63dfc60d8560e01b5f5260045ffd5b346101c35760203660031901126101c3576020610eac6004356121a1565b604051908152f35b81516001600160a01b031681526101e08101929161066c91906101c09081906020818101516001600160a01b0316908501526040818101516001600160a01b0316908501526060818101516001600160a01b0316908501526080818101516001600160a01b03169085015260a08181015165ffffffffffff169085015260c08181015165ffffffffffff169085015260e081015160e0850152610f6361010082015161010086019060ff169052565b610120810151610120850152610f8661014082015161014086019061ffff169052565b610160818101516001600160401b031690850152610180818101516001600160401b0316908501526101a08181015161ffff1690850152015160ff16910152565b346101c3575f3660031901126101c357610fdf6121db565b506107f6610feb61065c565b6001600160a01b037f00000000000000000000000012100faa7b157e9947340b44409fc7e27ec0abef1681527f0000000000000000000000009d1313add47c8b69882d6a4605df112fc501f3416001600160a01b031660208201527f000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e06001600160a01b031660408201527f000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb325442646001600160a01b031660608201527f00000000000000000000000000acc4d239aa05c797e038b7701be8be694014396001600160a01b0316608082015265ffffffffffff7f0000000000000000000000000000000000000000000000000000000000001c201660a082015265ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000b41660c08201527f000000000000000000000000000000000000000000000000000000000000006460e082015260ff7f000000000000000000000000000000000000000000000000000000000000004b166101008201527f000000000000000000000000000000000000000000000000000000000000000161012082015261ffff7f0000000000000000000000000000000000000000000000000000000000000000166101408201526001600160401b037f0000000000000000000000000000000000000000000000000000000000989680166101608201526001600160401b037f00000000000000000000000000000000000000000000000000000000000000321661018082015261ffff7f0000000000000000000000000000000000000000000000000000000000000180166101a082015260ff7f0000000000000000000000000000000000000000000000000000000000000005166101c082015260405191829182610eb4565b6004359061ffff821682036101c357565b6024359061ffff821682036101c357565b62ffffff8116036101c357565b60603660031901126101c3576113d760206040516112de816105b3565b6112e6611292565b81526112f06112a3565b82820152604435611300816112b4565b604082015260015f5260fe60205261133a7f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b7541515612248565b604080516312b2aa9160e31b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000989680811660248301527f0000000000000000000000000000000000000000000000000000000000000032166044820152825161ffff9081166064830152602084015116608482015291015162ffffff1660a4820152918290819060c4820190565b038173d1a27f331c17ed8cbb6dabce67a42d6b8a6b0e145af490811561097e575f91611410575b508061140657005b6104119033612fde565b611432915060203d602011611438575b61142a818361063b565b81019061225e565b5f6113fe565b503d611420565b346101c3575f3660031901126101c3576040516343c3d71960e01b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000989680811660248301527f000000000000000000000000000000000000000000000000000000000000003216604482015260208160648173d1a27f331c17ed8cbb6dabce67a42d6b8a6b0e145af4801561097e576107f6915f91611503575b506040516001600160401b0390911681529081906020820190565b611525915060203d60201161152b575b61151d818361063b565b81019061226d565b5f6114e8565b503d611513565b346101c3575f3660031901126101c3576065546040516001600160a01b039091168152602090f35b346101c35761156836610c45565b9261158e61158961157833613016565b9261158161210b565b9536916106d4565b61319e565b9283519361159c85836132f4565b9290919365ffffffffffff84169283155f14611b16576020890151945b6115c960a08401968751146122c6565b60408a01976115e289516115dc856121a1565b146122dc565b15611b06575b50602083015115158015611abc575b6119bf575b65ffffffffffff16604082015265ffffffffffff4216606082019081529360c08901958651905f190161162e916122b2565b5160600151905261163e90612048565b61164661067d565b90815261165290613612565b604051611660819282612316565b037fb2d5049ba96efb9e1fee66a51e4e6cbdfa2949627891ee29c6e4281abb8da03c91a1825190611690916122b2565b516040015190516116ac9165ffffffffffff918216911661374f565b4203936116b881613761565b92604051806116d38682919060206040840193600181520152565b035f51602061424b5f395f51905f5291a18151604080516002815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a1602082015160405161173f819282919060206040840193600381520152565b035f51602061424b5f395f51905f5291a15160405161176b819282919060206040840193600481520152565b035f51602061424b5f395f51905f5291a1606081015160408051600581526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a16080810151604080516006815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a160a00151604051611819819282919060206040840193600781520152565b035f51602061424b5f395f51905f5291a18051611835906122a0565b5160600151604051611854819282919060206040840193600881520152565b035f51602061424b5f395f51905f5291a18051611870906122a0565b515160408051600981526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a180516118b8906122a0565b5160209081015160408051600a81526001600160a01b03909216928201929092527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba9190a151611907906122a0565b516040908101518151600b815265ffffffffffff90911660208201527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b147749190a17f0000000000000000000000009d1313add47c8b69882d6a4605df112fc501f3416001600160a01b031690813b156101c3575f9361199b604051968795869485946314bcf3dd60e01b86526004860161234a565b03915afa801561097e576119ab57005b806119b95f6104119361063b565b806101b9565b60808901517f00000000000000000000000000acc4d239aa05c797e038b7701be8be694014396001600160a01b0316919065ffffffffffff16918a6060611a1360c060a08401519301515f198c01906122b2565b510151611a2f611a2161066e565b65ffffffffffff9096168652565b60208501526040840152803b156101c35760408051631934171960e31b8152845165ffffffffffff1660048201526020850151602482015293015160448401525f908390606490829084905af191821561097e5765ffffffffffff92611aa8575b5065ffffffffffff42831616608084015290506115fc565b806119b95f611ab69361063b565b5f611a90565b5065ffffffffffff611ad7608084015165ffffffffffff1690565b61ffff7f00000000000000000000000000000000000000000000000000000000000001801601164210156115f7565b611b10908a61340c565b5f6115e8565b6060611b3260c08b015165ffffffffffff5f19890116906122b2565b510151946115b9565b346101c35760203660031901126101c357600435611b5881610230565b611b606128a0565b606580546001600160a01b0319166001600160a01b039283169081179091556033549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b15611bb257565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b15611c1557565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b15611c7657565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b90611cda826106b9565b611ce7604051918261063b565b8281528092611cf8601f19916106b9565b0190602036910137565b519061066c82610483565b6001600160401b0381116104135760051b60200190565b519081151582036101c357565b519061066c826112b4565b91906080838203126101c357604051611d54816105ce565b80938051611d6181610483565b825260208101516020830152604081015160ff811681036101c35760408301526060810151906001600160401b0382116101c357019180601f840112156101c3578251611dad81611d0d565b93611dbb604051958661063b565b81855260208086019260051b820101908382116101c35760208101925b828410611dea57505050505060600152565b83516001600160401b0381116101c35782016040818703601f1901126101c35760405190611e17826105e9565b611e2360208201611d24565b825260408101516001600160401b0381116101c35760209101016060818803126101c35760405190611e54826105b3565b80516001600160401b0381116101c357810188601f820112156101c357805190611e7d82611d0d565b91611e8b604051938461063b565b80835260208084019160051b830101918b83116101c357602001905b828210611eea5750505091611ed6604060209694938796948452611ecc878201611d31565b8785015201611d02565b604082015283820152815201930192611dd8565b8151815260209182019101611ea7565b91908260c09103126101c357604051611f1281610604565b60a08082948051611f2281610483565b84526020810151611f3281610483565b60208501526040810151611f4581610483565b60408501526060810151611f5881610230565b6060850152608081015160808501520151910152565b9190828103926101e084126101c35760c08151611f8a81610483565b94601f1901126101c357604051611fa081610604565b6020820151611fae81610483565b81526040820151611fbe81610483565b60208201526060820151611fd181610483565b60408201526080820151611fe481610483565b606082015260a0820151611ff781610483565b608082015260c082015160a08201529260e08201516001600160401b0381116101c35761203761202c856101c0938601611d3c565b946101008501611efa565b92015190565b6040513d5f823e3d90fd5b805160fc805460208401516040850151606080870151608088015165ffffffffffff60c01b60c09190911b166001600160f01b031990951665ffffffffffff909716969096176bffffffffffff00000000000060309490941b9390931692909217911b65ffffffffffff60601b161760909390931b65ffffffffffff60901b169290921791909117905560a0015160fd55565b604051906120e882610604565b5f60a0838281528260208201528260408201528260608201528260808201520152565b6040519061211882610604565b8161216365ffffffffffff60fc548181168452818160301c166020850152818160601c16604085015281808260901c1616606085015260c01c16608083019065ffffffffffff169052565b60a060fd54910152565b1561217457565b63ba74d80f60e01b5f5260045ffd5b811561218d570690565b634e487b7160e01b5f52601260045260245ffd5b6121cc907f000000000000000000000000000000000000000000000000000000000000006490612183565b5f5260fe60205260405f205490565b604051906121e88261061f565b5f6101c0838281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a08201520152565b1561224f57565b63f37a8b1360e01b5f5260045ffd5b908160209103126101c3575190565b908160209103126101c357516001600160401b03811681036101c35790565b634e487b7160e01b5f52603260045260245ffd5b8051156122ad5760200190565b61228c565b80518210156122ad5760209160051b010190565b156122cd57565b63198070b360e01b5f5260045ffd5b156122e357565b63f904c2fd60e01b5f5260045ffd5b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9060206123279281815201906122f2565b90565b908060209392818452848401375f828201840152601f01601f1916010190565b612327949260609282526020820152816040820152019161232a565b1561236d57565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b6123df60ff5f5460081c166123da81612366565b612366565b6001600160a01b03811661240857506123f733612bc0565b61010060c95461ff0019161760c955565b6123f790612bc0565b1561241857565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b906124ea7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b156124f9575061066c906139e2565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281612565575b506125435760405162461bcd60e51b81528061253f6004820161246f565b0390fd5b61066c926125605f51602061428b5f395f51905f525f9414612411565b613900565b61257f91935060203d6020116114385761142a818361063b565b915f612521565b906125b27f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b156125c1575061066c906139e2565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281612625575b506126075760405162461bcd60e51b81528061253f6004820161246f565b61066c926125605f51602061428b5f395f51905f5260019414612411565b61263f91935060203d6020116114385761142a818361063b565b915f6125e9565b1561264d57565b63bae6e2a960e01b5f5260045ffd5b60405190612669826105b3565b5f604083606081528260208201520152565b60405190612688826105e9565b815f8152602061269661265c565b910152565b604051906126aa60208361063b565b5f80835282815b8281106126bd57505050565b6020906126c861267b565b828285010152016126b1565b906126de82611d0d565b6126eb604051918261063b565b82815280926126fc601f1991611d0d565b01905f5b82811061270c57505050565b60209061271761267b565b82828501015201612700565b90604051612730816105b3565b80926040518060208354918281520190835f5260205f20905f5b81811061279757505050600161066c94938361276d60409561278a95038261063b565b8552015462ffffff8116602085015260181c65ffffffffffff1690565b65ffffffffffff16910152565b825484526020909301926001928301920161274a565b906040516127ba816105e9565b6020612696600183956001600160401b03815416855201612723565b6101005465ffffffffffff8281169493603083901c821693929091168510801561288e575b801561287e575b6128715761281d929165ffffffffffff809216920316613a7e565b612826816126d4565b925f5b82811061283557505050565b80612855612850846001940160ff905f5260205260405f2090565b6127ad565b61285f82886122b2565b5261286a81876122b2565b5001612829565b505050905061232761269b565b5065ffffffffffff811615612802565b5065ffffffffffff83168510156127fb565b6033546001600160a01b031633036128b457565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b7f0000000000000000000000000000000000000000000000000000000000000064801561218d57505f805260fe6020527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af55565b61297f9065ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000649116612183565b5f5260fe60205260405f2055565b906040519161299b836105e9565b82526129b96129b460606020850193808552015161402f565b611cd0565b91612a6f612a60612a52612a42612a34612a21612a0e6129f360208b016129e88a5165ffffffffffff90511690565b60d01b815260060190565b8851606001516001600160a01b03165b60601b815260140190565b87516020015165ffffffffffff166129e8565b86516040015165ffffffffffff166129e8565b855160800151815260200190565b85515165ffffffffffff166129e8565b845160209081015182520190565b83516040015160ff1690614026565b91612a9b6060825101515193612a848561400d565b6001600160f01b031960f086901b16815260020190565b925f915b818310612ae8575050905160a00151909152506040517f10b2060c55406ea48522476f67fd813d4984b12078555d3e2a377e35839d7d01918190612ae39082612316565b0390a1565b9091936020612b18612aff876060865101516122b2565b5192612b0b8451151590565b15612bb957600190614026565b910190612b438251515191612b2c8361400d565b6001600160f01b031960f084901b16815260020190565b905f905b808210612b94575050816129e86040612b7c612b8b94612b716020600198510162ffffff90511690565b60e81b815260030190565b9251015165ffffffffffff1690565b94019190612a9f565b9091612bb1600191612ba8858751516122b2565b51815260200190565b920190612b47565b5f90614026565b606580546001600160a01b0319908116909155603380549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b5165ffffffffffff168015908115612c3d575b5015612c2e57565b63559895a360e01b5f5260045ffd5b90504211155f612c26565b60405190612c55826105ce565b606080835f81525f60208201525f60408201520152565b15612c7357565b6349517a1d60e11b5f5260045ffd5b15612c8957565b63eaabac9b60e01b5f5260045ffd5b908160209103126101c3575161232781610483565b6001600160a01b0390911681526040602082018190526123279391019161232a565b94612d3890612cff65ffffffffffff612d3f94959697612ced6120db565b50612cf6612c48565b50164311612c6c565b5f1965ffffffffffff918703821681019091167f0000000000000000000000000000000000000000000000000000000000000064030190565b1515612c82565b612d98612d6f6020612d67612d61612d5b60408a015160ff1690565b60ff1690565b33613acc565b960151613c84565b612d7761068c565b905f8252602082015285515f1981510191612d9283836122b2565b526122b2565b50602084015115612e525750505f5b5f1943019251612db561069b565b65ffffffffffff851681529340602085015260ff7f000000000000000000000000000000000000000000000000000000000000004b166040850152606084015282612e3f612e16612e105f19860165ffffffffffff166121a1565b92613d6d565b92612e22611a216106aa565b4265ffffffffffff16602086015265ffffffffffff166040850152565b336060840152608083015260a082015291565b604051635600026d60e11b81529160209183918291612e7691903360048501612cad565b03815f7f000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e06001600160a01b03165af190811561097e575f91612eb9575b50612da7565b612edb915060203d602011612ee1575b612ed3818361063b565b810190612c98565b5f612eb3565b503d612ec9565b612fb560a060405192600684528360e001604052612f26612f1d612f12835165ffffffffffff1690565b65ffffffffffff1690565b60208601528490565b50612f49612f40612f12602084015165ffffffffffff1690565b60408601528490565b50612f6c612f63612f12604084015165ffffffffffff1690565b60608601528490565b506060810151612f9f90612f9690612f8a906001600160a01b031681565b6001600160a01b031690565b60808601528490565b50608081015160a0850152015160c08301528190565b50805160051b6020820120612327905b918051604051828260010160051b011490151060061b52565b61066c915a91613f61565b91908260409103126101c357602061203783611d24565b1561300757565b63c1a58f1960e01b5f5260045ffd5b7f000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb325442646001600160a01b03169081156130c95760408051633326844b60e11b81526001600160a01b0390921660048301529091829060249082905afa801561097e575f915f91613098575b50156130935761308e90613000565b600190565b505f90565b90506130bc915060403d6040116130c2575b6130b4818361063b565b810190612fe9565b5f61307f565b503d6130aa565b50505f90565b604051906130dc826105e9565b60405160e08101836001600160401b03821183831017610413575f9260209260405283815283838201528360408201528360608201528360808201528360a0820152606060c082015281520152565b60405190613138826105ce565b5f6060838281528260208201528260408201520152565b9061315982611d0d565b613166604051918261063b565b8281528092613177601f1991611d0d565b01905f5b82811061318757505050565b60209061319261312b565b8282850101520161317b565b9061ffff61326261324e6131ea61323a61322d6132196132056131f46131ea6131d960206131ca6130cf565b9d01906006825160d01c920190565b91908d519065ffffffffffff169052565b9060208251920190565b9060208c5101529060208251920190565b9060408b510152906014825160601c920190565b919060608a51019060018060a01b03169052565b906006825160d01c920190565b919060808851019065ffffffffffff169052565b9060a086510152906002825160f01c920190565b911661326d8161314f565b60c0855101525f905b80821061328c5750505160f81c15156020830152565b9091613299600191613fa9565b93906132aa8260c0895101516122b2565b520190613276565b156132b957565b6363db3a4160e01b5f5260045ffd5b156132cf57565b63677c56f160e01b5f5260045ffd5b156132e557565b63181432e760e11b5f5260045ffd5b909165ffffffffffff60018160408501511601169260c08101515193841561339d57613390612f12836133438465ffffffffffff61333b612327985165ffffffffffff1690565b1611156132b2565b613378613371612f125f198b613362612f12875165ffffffffffff1690565b0101995165ffffffffffff1690565b88106132c8565b613384848810156132de565b5165ffffffffffff1690565b900365ffffffffffff1690565b63c2e5347d60e01b5f5260045ffd5b815165ffffffffffff168152602082015160808201939260028210156133f85760208301919091526040818101516001600160a01b039081169184019190915260609182015116910152565b634e487b7160e01b5f52602160045260245ffd5b9060c082019182516134a661343d604061342f65ffffffffffff871680956122b2565b51015165ffffffffffff1690565b65ffffffffffff8061345a60fc5465ffffffffffff9060901c1690565b7f00000000000000000000000000000000000000000000000000000000000000b40116917f0000000000000000000000000000000000000000000000000000000000001c20011661374f565b42111561360c5761350660606134f760206134e8613529956134e1613539996134d58a5165ffffffffffff1690565b0165ffffffffffff1690565b99516122b2565b5101516001600160a01b031690565b9301516001600160a01b031690565b91613512611a2161069b565b600160208601526001600160a01b03166040850152565b6001600160a01b03166060830152565b613566602061354783613fe4565b6040518093819263019b28af60e61b8352600483019190602083019252565b03815f7f00000000000000000000000000acc4d239aa05c797e038b7701be8be694014396001600160a01b03165af1801561097e576135ef575b507f8796b99bbf275a983988181e85b42502d9347327f4dde674320bec3879bcc5e16135ea65ffffffffffff6135dc845165ffffffffffff1690565b1692604051918291826133ac565b0390a2565b6136079060203d6020116114385761142a818361063b565b6135a0565b50505050565b908151519060c08201916136c06136a36136346129b4865151604e0260830190565b9260a061369861368661367361366661365a60208a016129e8885165ffffffffffff1690565b60208781015182520190565b6040860151815260200190565b60608501516001600160a01b0316612a03565b608084015165ffffffffffff166129e8565b910151815260200190565b6136ae85515161400d565b84515161ffff1660f01b815260020190565b915f925b84518051851015613733576001916136df8661372b936122b2565b518051606090811b6bffffffffffffffffffffffff1990811684526020830151821b166014840152604082015160d01b6001600160d01b03191660288401520151602e820152604e0190565b9301926136c4565b509194612b0b91945061374c9350602090510151151590565b50565b908082111561375c575090565b905090565b60c081015180519061381d60a061378d8460021b60090190604051828193825260010160051b01604052565b602080820152946137b36137aa612f12835165ffffffffffff1690565b60408801528690565b50602081015160608701526040810151608087015260608101516137ee906137e590612f8a906001600160a01b031681565b60a08801528690565b50613811613808612f12608084015165ffffffffffff1690565b60c08801528690565b50015160e08501528390565b5060e061010084015261012083018290525f9060095b8383106138525750505050612327612fc5826020815160051b91012090565b60046001916138f6606061386687876122b2565b51805161388f9061388190612f8a906001600160a01b031681565b6001860160051b8c01528a90565b5060208101516138bd906138ad90612f8a906001600160a01b031681565b60018689010160051b8c01528a90565b506138e56138d7612f12604084015165ffffffffffff1690565b6003860160051b8c01528a90565b5001516004830160051b8901528790565b5001920191613833565b9161390a836139e2565b6001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2815115908115916139da575b5061394d575050565b61374c915f806040519361396260608661063b565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020860152660819985a5b195960ca1b6040860152602081519101845af43d156139d2573d916139b6836106b9565b926139c4604051948561063b565b83523d5f602085013e6141b1565b6060916141b1565b90505f613944565b803b15613a235760018060a01b03166bffffffffffffffffffffffff60a01b5f51602061428b5f395f51905f525416175f51602061428b5f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b8181111561375c575090565b60015f51602061426b5f395f51905f525d565b60405190613aaa826105e9565b5f602083606081520152565b15613abd57565b63014b3fdb60e11b5f5260045ffd5b919065ffffffffffff61066c91613ae1613a9d565b9461010054613b07613af88265ffffffffffff1690565b9160301c65ffffffffffff1690565b91613b348583850316918286115f14613c0657829384915b613b2b600184016126d4565b90818d52614066565b9290947f0000000000000000000000000000000000000000000000000000000000000001119182613bfc575b5050613bbe575b50501660ff7f00000000000000000000000000000000000000000000000000000000000000051661ffff7f000000000000000000000000000000000000000000000000000000000000000016020142116020840152565b610278613bf091613bf5937f000000000000000000000000000000000000000000000000000000000000000091614173565b613ab6565b5f80613b67565b1190505f80613b60565b85938491613b1f565b15613c1657565b63fdac229f60e01b5f5260045ffd5b90613c2f82611d0d565b613c3c604051918261063b565b8281528092611cf8601f1991611d0d565b91908201809211613c5a57565b634e487b7160e01b5f52601160045260245ffd5b15613c7557565b637bb2fa2f60e11b5f5260045ffd5b90613c8d61265c565b506020820191613cad61ffff613ca5855161ffff1690565b161515613c0f565b613ccb613cc6613cbf855161ffff1690565b61ffff1690565b613c25565b915f5b613cdd613cbf865161ffff1690565b811015613d2f57613cbf600182613d05613cdd94613d00613cbf895161ffff1690565b613c4d565b49613d1082896122b2565b52613d26613d1e82896122b2565b511515613c6e565b01915050613cce565b509250613d456040613d5c92015162ffffff1690565b613d4d61066e565b92835262ffffff166020830152565b4265ffffffffffff16604082015290565b606081015180519081600601805f5b848110613f2b5750612f96612d5b6040613da8613de19490604051828193825260010160051b01604052565b60208082015297613dce613dc5612f12835165ffffffffffff1690565b60408b01528990565b50602081015160608a0152015160ff1690565b50608060a085015260c08401839052905f915b838310613e135750505050612327612fc5826020815160051b91012090565b6020613e1f84846122b2565b51613e39600519840160051b6007870160051b8901528790565b50805115613f2057613e5860ff60015b166001850160051b8901528790565b5060406002840160051b88015260606003840160051b88015201613ea0613e92613e8a602084510162ffffff90511690565b62ffffff1690565b6004840160051b8801528690565b50613eca613ebc612f12604084510165ffffffffffff90511690565b6005808501901b8801528690565b50515180516006830160051b870181905291905f5b838110613ef85750506001916006910101920191613df4565b80613f19613f08600193856122b2565b5160078684010160051b8b01528990565b5001613edf565b613e5860ff5f613e49565b9060066001916020613f3d85886122b2565b510151515101019101613d7c565b15613f5257565b634c67134d60e11b5f5260045ffd5b91908015613fa45761066c925f92839260405192613f8060208561063b565b848452613f976001600160a01b0382161515613f4b565b60208451940192f1613f4b565b505050565b613fb161312b565b91815160601c8352601482015160601c6020840152602882015160d01c6040840152604e602e8301519201916060840152565b60405161400781613ff96020820194856133ac565b03601f19810183528261063b565b51902090565b61ffff1061401757565b63161e7a6b60e11b5f5260045ffd5b60019181530190565b5f9190608f5b815184101561406157600c600191602061404f87866122b2565b510151515160051b0101930192614035565b925050565b9392938415614164575f905f5b8681106140ea57506040602061409e65ffffffffffff9695856140ae9589976140d3575b50506122a0565b510151015165ffffffffffff1690565b941601169061066c826101009065ffffffffffff1665ffffffffffff19825416179055565b633b9aca006140e3920290612fde565b5f80614097565b9160019061415c6141506141118665ffffffffffff8a160160ff905f5260205260405f2090565b61411961068c565b60018152614128868301612723565b6020820152614137888a6122b2565b5261414287896122b2565b50546001600160401b031690565b6001600160401b031690565b019201614073565b5050915065ffffffffffff9190565b65ffffffffffff809116911681146130c9575f5260ff60205265ffffffffffff600260405f20015460181c169081156130c95761ffff160142101590565b9192901561421357508151156141c5575090565b3b156141ce5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156142265750805190602001fd5b60405162461bcd60e51b81526020600482015290819061253f9060248301906122f256fe712de588b76f7fdb47439ab8677a0c8233392168ef0308d402c7b8d72138a080a5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220664da4c6aa12e8168ded1ddf7dcf200d84f7ca508d47d95178e7b1a107f3eafb64736f6c634300081e0033