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-15T07:41:29.425764Z
Constructor Arguments
0x000000000000000000000000f4c259d287cc39e197b1148a198227472ca50b65000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e0000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb3254426400000000000000000000000000acc4d239aa05c797e038b7701be8be6940143900000000000000000000000012100faa7b157e9947340b44409fc7e27ec0abef
Arg [0] (address) : 0xf4c259d287cc39e197b1148a198227472ca50b65
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/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);
}
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/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
);
// ---------------------------------------------------------------
// 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);
_proofVerifier.verifyProof(
proposalAge, LibHashOptimized.hashCommitment(commitment), _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;
}
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_);
}
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);
}
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":false,"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":"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
0x6102a060405230608052348015610014575f5ffd5b506040516149f63803806149f6833981016040819052610033916102d2565b604080516101e0810182526001600160a01b03808416825287811660208301528681169282019290925284821660608201529083166080820152611c2060a082015260b460c0820152606460e0820152604b61010082015260016101208201525f610140820152629896806101608201526032610180808301919091526101a082015260056101c08201526100c66101fb565b6040516348ed17ff60e11b8152739c9d925f3d7d820a994811c17480fe67875a1562906391da2ffe906100fd908490600401610333565b5f6040518083038186803b158015610113575f5ffd5b505af4158015610125573d5f5f3e3d5ffd5b505082516001600160a01b0390811660c09081526020850151821660e09081526040860151831661010090815260608701518416610120908152608088015190941661014090815260a088015165ffffffffffff9081166101609081529489015116610180908152928801516101a09081529188015160ff9081166101c0908152958901516101e0529088015161ffff90811661020052938801516001600160401b0390811661022052928801519092166102405286015190911661026052930151909216610280525061049995505050505050565b5f54610100900460ff16156102665760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116146102b5575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146102cd575f5ffd5b919050565b5f5f5f5f5f60a086880312156102e6575f5ffd5b6102ef866102b7565b94506102fd602087016102b7565b935061030b604087016102b7565b9250610319606087016102b7565b9150610327608087016102b7565b90509295509295909350565b81516001600160a01b031681526101e08101602083015161035f60208401826001600160a01b03169052565b50604083015161037a60408401826001600160a01b03169052565b50606083015161039560608401826001600160a01b03169052565b5060808301516103b060808401826001600160a01b03169052565b5060a08301516103ca60a084018265ffffffffffff169052565b5060c08301516103e460c084018265ffffffffffff169052565b5060e083015160e083015261010083015161040561010084018260ff169052565b5061012083015161012083015261014083015161042961014084018261ffff169052565b506101608301516104466101608401826001600160401b03169052565b506101808301516104636101808401826001600160401b03169052565b506101a083015161047b6101a084018261ffff169052565b506101c08301516104926101c084018260ff169052565b5092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516143f96105fd5f395f818161082f0152612e9201525f8181610805015261143601525f81816107d601528181611137015261123f01525f81816107a70152818161110f015261121701525f818161077d01528181612e410152612eb601525f81816107570152612e0701525f818161072e01526120bf01525f81816107080152818161106d01528181611d010152611f5901525f81816106da015261254801525f81816106ac015261258901525f818161067d01528181611472015261266a01525f818161064e01528181612207015261225d01525f818161061f015261201401525f81816105f0015261173301525f6105c101525f6101c701525f8181610a1c01528181610a5c01528181610b5501528181610b950152610c0c01526143f95ff3fe60806040526004361061017b575f3560e01c8063715018a6116100cd578063a834725a11610087578063e305333511610062578063e305333514610879578063e30c3978146108a5578063ea191743146108c2578063f2fde38b146108e1575f5ffd5b8063a834725a1461050d578063c3f909d41461052c578063df596d9e14610866575f5ffd5b8063715018a61461048157806379ba5097146104955780638456cb59146104a95780638abf6077146104bd5780638da5cb5b146104d15780639791e644146104ee575f5ffd5b806340df98661161013857806359db6e851161011357806359db6e85146102f95780635c975abb146103185780635ccc1718146103385780636aa6a01a1461036e575f5ffd5b806340df9866146102985780634f1ef286146102c457806352d1902d146102d7575f5ffd5b80630423c7de1461017f57806304f3bcec146101b957806319ab453c146101ff5780633075db56146102205780633659cfe6146102655780633f4ba83a14610284575b5f5ffd5b34801561018a575f5ffd5b5060fb5461019d9065ffffffffffff1681565b60405165ffffffffffff90911681526020015b60405180910390f35b3480156101c4575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020016101b0565b34801561020a575f5ffd5b5061021e610219366004613796565b610900565b005b34801561022b575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b60405190151581526020016101b0565b348015610270575f5ffd5b5061021e61027f366004613796565b610a12565b34801561028f575f5ffd5b5061021e610ad9565b3480156102a3575f5ffd5b506102b76102b23660046137c4565b610b34565b6040516101b091906137fb565b61021e6102d23660046139ab565b610b4b565b3480156102e2575f5ffd5b506102eb610c00565b6040519081526020016101b0565b348015610304575f5ffd5b5061021e610313366004613a50565b610cb1565b348015610323575f5ffd5b5061025560c954610100900460ff1660021490565b348015610343575f5ffd5b50610100546040805165ffffffffffff8084168252600160301b9093049092166020830152016101b0565b348015610379575f5ffd5b5061040e6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260fc5465ffffffffffff8082168352600160301b820481166020840152600160601b8204811693830193909352600160901b810483166060830152600160c01b9004909116608082015260fd5460a082015290565b6040516101b091905f60c08201905065ffffffffffff835116825265ffffffffffff602084015116602083015265ffffffffffff604084015116604083015265ffffffffffff606084015116606083015265ffffffffffff608084015116608083015260a083015160a083015292915050565b34801561048c575f5ffd5b5061021e610e63565b3480156104a0575f5ffd5b5061021e610e74565b3480156104b4575f5ffd5b5061021e610eeb565b3480156104c8575f5ffd5b506101e7610f40565b3480156104dc575f5ffd5b506033546001600160a01b03166101e7565b3480156104f9575f5ffd5b5061021e610508366004613aab565b610f4e565b348015610518575f5ffd5b506102eb610527366004613a50565b611064565b348015610537575f5ffd5b50610859604080516101e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810191909152604051806101e001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000060ff1681526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000061ffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f000000000000000000000000000000000000000000000000000000000000000061ffff1681526020017f000000000000000000000000000000000000000000000000000000000000000060ff16815250905090565b6040516101b09190613b15565b61021e610874366004613ca1565b6110a7565b348015610884575f5ffd5b5061088d6111f9565b6040516001600160401b0390911681526020016101b0565b3480156108b0575f5ffd5b506065546001600160a01b03166101e7565b3480156108cd575f5ffd5b5061021e6108dc366004613aab565b6112c4565b3480156108ec575f5ffd5b5061021e6108fb366004613796565b6117c6565b5f54610100900460ff161580801561091e57505f54600160ff909116105b806109375750303b15801561093757505f5460ff166001145b61099f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff1916600117905580156109c0575f805461ff0019166101001790555b6109c982611837565b8015610a0e575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610a5a5760405162461bcd60e51b815260040161099690613cf1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610a8c611895565b6001600160a01b031614610ab25760405162461bcd60e51b815260040161099690613d3d565b610abb816118b0565b604080515f80825260208201909252610ad6918391906118b8565b50565b610ae1611a22565b610af560c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a1610b32335f611a53565b565b6060610b4260ff8484611a5b565b90505b92915050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b935760405162461bcd60e51b815260040161099690613cf1565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610bc5611895565b6001600160a01b031614610beb5760405162461bcd60e51b815260040161099690613d3d565b610bf4826118b0565b610a0e828260016118b8565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c9f5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610996565b505f51602061437d5f395f51905f5290565b610cb9611c9e565b60fb54604051633dd0723360e21b81526004810183905265ffffffffffff90911660248201525f908190819081908190739c9d925f3d7d820a994811c17480fe67875a15629063f741c8cc906044015f60405180830381865af4158015610d22573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d499190810190614041565b60fb805465ffffffffffff191665ffffffffffff87811691909117909155845160fc80546020880151604089015160608a015160808b01519587166bffffffffffffffffffffffff1990941693909317600160301b92871692909202919091176bffffffffffffffffffffffff60601b1916600160601b9186169190910265ffffffffffff60901b191617600160901b918516919091021765ffffffffffff60c01b1916600160c01b929093169190910291909117905560a084015160fd55939850919650945092509050610e1e5f82611cf8565b610e288284611d42565b6040518681527fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d29060200160405180910390a1505050505050565b610e6b611c9e565b610b325f611d9a565b60655433906001600160a01b03168114610ee25760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610996565b610ad681611d9a565b610ef3611db3565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a1610b32336001611a53565b5f610f49611895565b905090565b610f56611de5565b610f606002611e2a565b5f610f9f83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611e3392505050565b9050610faa81611e8b565b60fc5465ffffffffffff80821691600160301b8104821691600160601b9091041682610fe95760405163ba74d80f60e01b815260040160405180910390fd5b5f5f610ff9868b8b888888611ec7565b60fc80544365ffffffffffff908116600160301b026bffffffffffffffffffffffff1990921660018b019190911617179055815191935091506110449061103f84612168565b611cf8565b61104e8282611d42565b50505050505061105e6001611e2a565b50505050565b5f60fe816110927f000000000000000000000000000000000000000000000000000000000000000085614132565b81526020019081526020015f20549050919050565b60015f5260fe6020527f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b754806110f05760405163f37a8b1360e01b815260040160405180910390fd5b604080516312b2aa9160e31b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000166044820152835161ffff908116606483015260208501511660848201529083015162ffffff1660a48201525f90734c0dbff2abf9cbd7641cf38fc5765949a8e5b1bf9063959554889060c401602060405180830381865af41580156111be573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111e29190614151565b905080156111f4576111f433826121f9565b505050565b6040516343c3d71960e01b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f00000000000000000000000000000000000000000000000000000000000000001660448201525f90734c0dbff2abf9cbd7641cf38fc5765949a8e5b1bf906343c3d71990606401602060405180830381865af41580156112a0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f499190614168565b5f6112ce33612204565b6040805160c08101825260fc5465ffffffffffff8082168352600160301b82048116602080850191909152600160601b8304821684860152600160901b830482166060850152600160c01b90920416608083015260fd5460a08301528251601f8901829004820281018201909352878352929350915f916113689189908990819084018382808284375f9201919091525061230192505050565b80519091505f808061137a8685612471565b9250925092505f8165ffffffffffff165f146113c2578460c001516001830365ffffffffffff16815181106113b1576113b161418e565b6020026020010151606001516113c8565b84602001515b9050808760a00151146113ee5760405163198070b360e01b815260040160405180910390fd5b6113f783611064565b85604001511461141a5760405163f904c2fd60e01b815260040160405180910390fd5b87611429576114298583612542565b85602001518061146b57507f000000000000000000000000000000000000000000000000000000000000000061ffff1687608001510165ffffffffffff164210155b1561156a577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c9a0b8c86040518060600160405280886080015165ffffffffffff1681526020018860c0015160018903815181106114d5576114d561418e565b60200260200101516060015181526020018860a001518152506040518263ffffffff1660e01b815260040161152e9190815165ffffffffffff168152602080830151908201526040918201519181019190915260600190565b5f604051808303815f87803b158015611545575f5ffd5b505af1158015611557573d5f5f3e3d5ffd5b50505065ffffffffffff42166080890152505b65ffffffffffff80841660408901524216606088015260c085015180515f19860190811061159a5761159a61418e565b6020026020010151606001518760a00181815250508660fc5f820151815f015f6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506020820151815f0160066101000a81548165ffffffffffff021916908365ffffffffffff1602179055506040820151815f01600c6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506060820151815f0160126101000a81548165ffffffffffff021916908365ffffffffffff1602179055506080820151815f0160186101000a81548165ffffffffffff021916908365ffffffffffff16021790555060a082015181600101559050507fb2d5049ba96efb9e1fee66a51e4e6cbdfa2949627891ee29c6e4281abb8da03c6116c7604051806020016040528089815250612748565b6040516116d491906141d0565b60405180910390a15f61172d886060015165ffffffffffff168760c001518565ffffffffffff168151811061170b5761170b61418e565b60200260200101516040015165ffffffffffff1661287290919063ffffffff16565b420390507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166314bcf3dd8261176a89612887565b8e8e6040518563ffffffff1660e01b815260040161178b949392919061420a565b5f6040518083038186803b1580156117a1575f5ffd5b505afa1580156117b3573d5f5f3e3d5ffd5b5050505050505050505050505050505050565b6117ce611c9e565b606580546001600160a01b0383166001600160a01b031990911681179091556117ff6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f54610100900460ff1661185d5760405162461bcd60e51b815260040161099690614229565b6118656129de565b6118836001600160a01b0382161561187d5781611d9a565b33611d9a565b5060c9805461ff001916610100179055565b5f51602061437d5f395f51905f52546001600160a01b031690565b610ad6611c9e565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156118eb576111f483612a04565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611945575060408051601f3d908101601f1916820190925261194291810190614151565b60015b6119a85760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610996565b5f51602061437d5f395f51905f528114611a165760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610996565b506111f4838383612a9f565b611a3660c954610100900460ff1660021490565b610b325760405163bae6e2a960e01b815260040160405180910390fd5b610a0e611c9e565b600183015460609065ffffffffffff80821691600160301b90048116908516821180611a9757508065ffffffffffff168565ffffffffffff1610155b80611aa8575065ffffffffffff8416155b15611b1157604080515f8082526020820190925290611b07565b611af46040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b815260200190600190039081611ac25790505b5092505050611c97565b5f611b2965ffffffffffff8784038116908716612ac3565b9050806001600160401b03811115611b4357611b436138d9565b604051908082528060200260200182016040528015611ba657816020015b611b936040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b815260200190600190039081611b615790505b5093505f5b81811015611c925765ffffffffffff871681015f90815260208981526040918290208251808401845281546001600160401b0316815283516001830180546080818702840181019097526060830181815293969495870194929391928492918491840182828015611c3957602002820191905f5260205f20905b815481526020019060010190808311611c25575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff166040909101529052508551869083908110611c7f57611c7f61418e565b6020908102919091010152600101611bab565b505050505b9392505050565b6033546001600160a01b03163314610b325760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610996565b8060fe5f611d2e7f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff8716614132565b815260208101919091526040015f20555050565b60408051808201909152828152602081018290527f10b2060c55406ea48522476f67fd813d4984b12078555d3e2a377e35839d7d01611d8082612ad7565b604051611d8d91906141d0565b60405180910390a1505050565b606580546001600160a01b0319169055610ad681612cb1565b611dc760c954610100900460ff1660021490565b15610b325760405163bae6e2a960e01b815260040160405180910390fd5b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff1603610b325760405163dfc60d8560e01b815260040160405180910390fd5b610ad681612d02565b611e3b6136ed565b60208281015160d01c82526026830151828201805160f092831c905260288501518151921c9190920152602a830151905160e89190911c604091820152602d9092015160f81c9181019190915290565b805165ffffffffffff161580611eaa5750805165ffffffffffff164211155b610ad65760405163559895a360e01b815260040160405180910390fd5b6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152604080516080810182525f80825260208201819052918101919091526060808201528365ffffffffffff164311611f42576040516349517a1d60e11b815260040160405180910390fd5b5f611f7d868590035f1990810165ffffffffffff167f0000000000000000000000000000000000000000000000000000000000000000030190565b11611f9b5760405163eaabac9b60e01b815260040160405180910390fd5b5f611fad338a6040015160ff16612d28565b905060405180604001604052805f15158152602001611fcf8b60200151612eee565b9052815180515f198101908110611fe857611fe861418e565b60200260200101819052505f816020015161209257604051635600026d60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ac0004da9061204d9033908d908d90600401614274565b6020604051808303815f875af1158015612069573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061208d91906142a1565b612094565b5f5b90505f60014303905060405180608001604052808265ffffffffffff168152602001824081526020017f000000000000000000000000000000000000000000000000000000000000000060ff168152602001845f015181525093506040518060c001604052808965ffffffffffff1681526020014265ffffffffffff1681526020018365ffffffffffff168152602001336001600160a01b0316815260200161214760018b0365ffffffffffff16611064565b81526020016121558661302f565b8152509450505050965096945050505050565b604080516006815260e08101909152815165ffffffffffff1660208201525f90602083015165ffffffffffff166040820152604083015165ffffffffffff16606082015260608301516001600160a01b03166080820152608083015160a082015260a083015160c0820152805160051b6020820120611c978280516040516001820160051b83011490151060061b52565b610a0e82825a613234565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661223a57505f919050565b604051633326844b60e11b81526001600160a01b0383811660048301525f9182917f0000000000000000000000000000000000000000000000000000000000000000169063664d0896906024016040805180830381865afa1580156122a1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122c591906142bc565b91509150805f036122d957505f9392505050565b816122f75760405163c1a58f1960e01b815260040160405180910390fd5b5060019392505050565b612309613724565b602082810151825160d091821c90526026840151835190920191909152604683015182516040015260668301518251606091821c910152607a8301518251911c608091820152820151815160a09081019190915282015160a283019060f01c806001600160401b03811115612380576123806138d9565b6040519080825280602002602001820160405280156123d057816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161239e5790505b50835160c001525f5b8161ffff1681101561245f57604080516080810182525f8082526020820181815292820181815260608084019283528751811c84526014880151901c909352602886015160d01c909252602e850151909152604e8401855160c001518051849081106124475761244761418e565b602090810291909101019190915292506001016123d9565b50505160f81c15156020820152919050565b604082015160c082015151905f90819060010165ffffffffffff16836124aa5760405163c2e5347d60e01b815260040160405180910390fd5b845165ffffffffffff168110156124d4576040516363db3a4160e01b815260040160405180910390fd5b845186515f1965ffffffffffff92831687010194501683106125095760405163677c56f160e01b815260040160405180910390fd5b8083101561252a5760405163181432e760e11b815260040160405180910390fd5b845f015165ffffffffffff1681039150509250925092565b5f6125e97f000000000000000000000000000000000000000000000000000000000000000060fc5f0160129054906101000a900465ffffffffffff160165ffffffffffff167f00000000000000000000000000000000000000000000000000000000000000008560c001518565ffffffffffff16815181106125c6576125c661418e565b6020026020010151604001510165ffffffffffff1661287290919063ffffffff16565b90508042116125f757505050565b60408051608081019091528351830165ffffffffffff1681525f9060208101600181526020018560c001518565ffffffffffff168151811061263b5761263b61418e565b6020026020010151602001516001600160a01b0316815260200185606001516001600160a01b031681525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166366ca2bc06126a083613277565b6040518263ffffffff1660e01b81526004016126be91815260200190565b6020604051808303815f875af11580156126da573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fe9190614151565b50805f015165ffffffffffff167f8796b99bbf275a983988181e85b42502d9347327f4dde674320bec3879bcc5e18260405161273a91906142e6565b60405180910390a250505050565b80515160c08101515160609190604e02608301806001600160401b03811115612773576127736138d9565b6040519080825280601f01601f19166020018201604052801561279d576020820181803683370190505b50825160d090811b602083810191909152840151602683015260408401516046830152606080850151901b606683015260808085015190911b607a83015260a0808501519183019190915260c0840151519194508401906127fd906132a6565b60c08301515160f01b81526002015f5b8360c001515181101561284b57612841828560c0015183815181106128345761283461418e565b60200260200101516132c9565b915060010161280d565b5061286981865f015160200151612862575f6132fe565b60016132fe565b50505050919050565b5f8183116128805781610b42565b5090919050565b60c081015180515f919060096004820201836128b38260408051828152600190920160051b8201905290565b6020808201529050855165ffffffffffff166040820152602086015160608201526040860151608082015260608601516001600160a01b031660a0820152608086015165ffffffffffff1660c082015260a086015160e082015260e0610100820152610120810183905260095f5b848110156129ac575f86828151811061293c5761293c61418e565b602090810291909101015180516001600160a01b03166001850160051b860152905060208101516001600160a01b03166002840160051b850152604081015165ffffffffffff166003840160051b85015260608101516004840160051b8501525060049190910190600101612921565b50815160051b60208301206129d38380516040516001820160051b83011490151060061b52565b979650505050505050565b5f54610100900460ff16610b325760405162461bcd60e51b815260040161099690614229565b6001600160a01b0381163b612a715760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610996565b5f51602061437d5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b612aa88361330a565b5f82511180612ab45750805b156111f45761105e8383613349565b5f818311612ad15782610b42565b50919050565b60605f612aeb83602001516060015161336e565b9050806001600160401b03811115612b0557612b056138d9565b6040519080825280601f01601f191660200182016040528015612b2f576020820181803683370190505b5083515160d090811b6020838101919091528551606090810151901b60268401528551810151821b603a8401528551604090810151831b81850152865160800151604685015281870180515190931b6066850152825190910151606c84015290510151909250608c830190612ba59082906132fe565b60208501516060015151909150612bbb816132a6565b612bcb828260f01b815260020190565b91505f5b81811015612ca1575f8660200151606001518281518110612bf257612bf261418e565b60200260200101519050612c0e84825f0151612862575f6132fe565b60208201515151909450612c21816132a6565b612c31858260f01b815260020190565b94505f5b81811015612c7457612c6a8684602001515f01518381518110612c5a57612c5a61418e565b6020026020010151815260200190565b9550600101612c35565b5050602090810180519091015160e81b8452516040015160d01b6003840152600990920191600101612bcf565b5050925160a00151909252919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60408051808201909152606081525f60208201526101005460ff9065ffffffffffff80821691600160301b9004811690828203165f818711612d6a5786612d6c565b815b9050806001016001600160401b03811115612d8957612d896138d9565b604051908082528060200260200182016040528015612dec57816020015b612dd96040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b815260200190600190039081612da75790505b508087525f90612e019087908b9088866133b2565b955090507f000000000000000000000000000000000000000000000000000000000000000088108015612e3357508183115b15612e88575f612e658787877f0000000000000000000000000000000000000000000000000000000000000000613536565b90508015612e865760405163014b3fdb60e11b815260040160405180910390fd5b505b65ffffffffffff167f000000000000000000000000000000000000000000000000000000000000000060ff167f000000000000000000000000000000000000000000000000000000000000000061ffff1602014211602087015250939695505050505050565b604080516060808201835281525f6020808301829052928201529082015161ffff16612f2d5760405163fdac229f60e01b815260040160405180910390fd5b5f826020015161ffff166001600160401b03811115612f4e57612f4e6138d9565b604051908082528060200260200182016040528015612f77578160200160208202803683370190505b5090505f5b836020015161ffff16811015612fff578351612f9d90829061ffff16614347565b49828281518110612fb057612fb061418e565b602002602001018181525050818181518110612fce57612fce61418e565b60200260200101515f5f1b03612ff757604051637bb2fa2f60e11b815260040160405180910390fd5b600101612f7c565b50604080516060810182529182529283015162ffffff16602082015265ffffffffffff4216928101929092525090565b606081015180515f919060068101835b8281101561307b578381815181106130595761305961418e565b6020026020010151602001515f0151516006018201915080600101905061303f565b50604080518281526001830160051b8101909152602080820152855165ffffffffffff16604082015260208601516060820152604086015160ff166080820152608060a082015260c0810183905260068381015f5b85811015613201575f8782815181106130eb576130eb61418e565b60200260200101519050613114858386016005878703901b5f1b60019190910160051b82015290565b5061313d8584835f0151613128575f61312b565b60015b60ff1660019190910160051b82015290565b5060406002840160051b86015260606003840160051b86015260028301602080830151015162ffffff166002820160051b87015260208201516040015165ffffffffffff166003820160051b87015260208201515180516004830160051b8801819052600383015f5b828110156131ea576131e18a8284600101018684815181106131ca576131ca61418e565b602002602001015160019190910160051b82015290565b506001016131a6565b5001600190810195509390930192506130d0915050565b50825160051b60208401206132288480516040516001820160051b83011490151060061b52565b98975050505050505050565b815f0361324057505050565b61325a83838360405180602001604052805f81525061359f565b6111f457604051634c67134d60e11b815260040160405180910390fd5b5f8160405160200161328991906142e6565b604051602081830303815290604052805190602001209050919050565b61ffff811115610ad65760405163161e7a6b60e11b815260040160405180910390fd5b8051606090811b83526020820151811b6014840152604082015160d01b6028840152810151602e8301908152604e8301610b42565b5f818353505060010190565b61331381612a04565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b42838360405180606001604052806027815260200161439d602791396135dc565b608f5f5b8251811015612ad15782818151811061338d5761338d61418e565b6020026020010151602001515f015151602002600c0182019150806001019050613372565b5f5f825f036133cb575065ffffffffffff90508261352c565b5f5f5b848110156134bb5765ffffffffffff861681015f90815260208a81526040918290208251808401845260018082528451908301805460808187028401810190975260608301818152949693958601949293919284929091849184018282801561345457602002820191905f5260205f20905b815481526020019060010190808311613440575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff16604090910152905288518990849081106134995761349961418e565b6020908102919091010152546001600160401b031691909101906001016133ce565b5080156134db576134db6001600160a01b038816633b9aca0083026121f9565b855f815181106134ed576134ed61418e565b602002602001015160200151604001519250838501915081886001015f6101000a81548165ffffffffffff021916908365ffffffffffff160217905550505b9550959350505050565b5f8265ffffffffffff168465ffffffffffff160361355557505f613597565b65ffffffffffff8085165f90815260208790526040812060020154630100000090049091169081900361358b575f915050613597565b61ffff83160142101590505b949350505050565b5f6001600160a01b0385166135c757604051634c67134d60e11b815260040160405180910390fd5b5f5f835160208501878988f195945050505050565b60605f5f856001600160a01b0316856040516135f89190614366565b5f60405180830381855af49150503d805f8114613630576040519150601f19603f3d011682016040523d82523d5f602084013e613635565b606091505b509150915061364686838387613650565b9695505050505050565b606083156136be5782515f036136b7576001600160a01b0385163b6136b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610996565b5081613597565b61359783838151156136d35781518083602001fd5b8060405162461bcd60e51b815260040161099691906141d0565b60408051606080820183525f8083528351918201845280825260208281018290529382015290918201905b81525f60209091015290565b60405180604001604052806137186040518060e001604052805f65ffffffffffff1681526020015f81526020015f81526020015f6001600160a01b031681526020015f65ffffffffffff1681526020015f8152602001606081525090565b6001600160a01b0381168114610ad6575f5ffd5b5f602082840312156137a6575f5ffd5b8135611c9781613782565b65ffffffffffff81168114610ad6575f5ffd5b5f5f604083850312156137d5575f5ffd5b82356137e0816137b1565b915060208301356137f0816137b1565b809150509250929050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156138cd57868503603f19018452815180516001600160401b0316865260209081015160408288018190528151606091890191909152805160a08901819052919201905f9060c08901905b80831015613892578351825260208201915060208401935060018301925061386f565b5060208481015162ffffff1660608b015260409094015165ffffffffffff166080909901989098525050938401939190910190600101613821565b50929695505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561390f5761390f6138d9565b60405290565b604051608081016001600160401b038111828210171561390f5761390f6138d9565b604080519081016001600160401b038111828210171561390f5761390f6138d9565b60405160c081016001600160401b038111828210171561390f5761390f6138d9565b604051601f8201601f191681016001600160401b03811182821017156139a3576139a36138d9565b604052919050565b5f5f604083850312156139bc575f5ffd5b82356139c781613782565b915060208301356001600160401b038111156139e1575f5ffd5b8301601f810185136139f1575f5ffd5b80356001600160401b03811115613a0a57613a0a6138d9565b613a1d601f8201601f191660200161397b565b818152866020838501011115613a31575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215613a60575f5ffd5b5035919050565b5f5f83601f840112613a77575f5ffd5b5081356001600160401b03811115613a8d575f5ffd5b602083019150836020828501011115613aa4575f5ffd5b9250929050565b5f5f5f5f60408587031215613abe575f5ffd5b84356001600160401b03811115613ad3575f5ffd5b613adf87828801613a67565b90955093505060208501356001600160401b03811115613afd575f5ffd5b613b0987828801613a67565b95989497509550505050565b81516001600160a01b031681526101e081016020830151613b4160208401826001600160a01b03169052565b506040830151613b5c60408401826001600160a01b03169052565b506060830151613b7760608401826001600160a01b03169052565b506080830151613b9260808401826001600160a01b03169052565b5060a0830151613bac60a084018265ffffffffffff169052565b5060c0830151613bc660c084018265ffffffffffff169052565b5060e083015160e0830152610100830151613be761010084018260ff169052565b50610120830151610120830152610140830151613c0b61014084018261ffff169052565b50610160830151613c286101608401826001600160401b03169052565b50610180830151613c456101808401826001600160401b03169052565b506101a0830151613c5d6101a084018261ffff169052565b506101c0830151613c746101c084018260ff169052565b5092915050565b803561ffff81168114613c8c575f5ffd5b919050565b62ffffff81168114610ad6575f5ffd5b5f6060828403128015613cb2575f5ffd5b50613cbb6138ed565b613cc483613c7b565b8152613cd260208401613c7b565b60208201526040830135613ce581613c91565b60408201529392505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b8051613c8c816137b1565b5f6001600160401b03821115613dac57613dac6138d9565b5060051b60200190565b80518015158114613c8c575f5ffd5b8051613c8c81613c91565b5f60808284031215613de0575f5ffd5b613de8613915565b90508151613df5816137b1565b815260208281015190820152604082015160ff81168114613e14575f5ffd5b604082015260608201516001600160401b03811115613e31575f5ffd5b8201601f81018413613e41575f5ffd5b8051613e54613e4f82613d94565b61397b565b8082825260208201915060208360051b850101925086831115613e75575f5ffd5b602084015b83811015613fb55780516001600160401b03811115613e97575f5ffd5b85016040818a03601f19011215613eac575f5ffd5b613eb4613937565b613ec060208301613db6565b815260408201516001600160401b03811115613eda575f5ffd5b6020818401019250506060828b031215613ef2575f5ffd5b613efa6138ed565b82516001600160401b03811115613f0f575f5ffd5b8301601f81018c13613f1f575f5ffd5b8051613f2d613e4f82613d94565b8082825260208201915060208360051b85010192508e831115613f4e575f5ffd5b6020840193505b82841015613f70578351825260209384019390910190613f55565b845250613f8291505060208401613dc5565b6020820152613f9360408401613d89565b6040820152806020830152508085525050602083019250602081019050613e7a565b5060608501525091949350505050565b5f60c08284031215613fd5575f5ffd5b613fdd613959565b90508151613fea816137b1565b81526020820151613ffa816137b1565b6020820152604082015161400d816137b1565b6040820152606082015161402081613782565b60608201526080828101519082015260a09182015191810191909152919050565b5f5f5f5f5f8587036101e0811215614057575f5ffd5b8651614062816137b1565b955060c0601f1982011215614075575f5ffd5b5061407e613959565b602087015161408c816137b1565b8152604087015161409c816137b1565b602082015260608701516140af816137b1565b604082015260808701516140c2816137b1565b606082015260a08701516140d5816137b1565b608082015260c087015160a082015260e08701519094506001600160401b038111156140ff575f5ffd5b61410b88828901613dd0565b93505061411c876101008801613fc5565b6101c09690960151949793965091949392915050565b5f8261414c57634e487b7160e01b5f52601260045260245ffd5b500690565b5f60208284031215614161575f5ffd5b5051919050565b5f60208284031215614178575f5ffd5b81516001600160401b0381168114611c97575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610b4260208301846141a2565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b848152836020820152606060408201525f6136466060830184866141e2565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03841681526040602082018190525f9061429890830184866141e2565b95945050505050565b5f602082840312156142b1575f5ffd5b8151611c97816137b1565b5f5f604083850312156142cd575f5ffd5b6142d683613db6565b6020939093015192949293505050565b815165ffffffffffff168152602082015160808201906002811061431857634e487b7160e01b5f52602160045260245ffd5b60208301526040838101516001600160a01b039081169184019190915260609384015116929091019190915290565b80820180821115610b4557634e487b7160e01b5f52601160045260245ffd5b5f82518060208501845e5f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d4f1ac9fd49ea7eee6187da54098c4e23fef4ba2c14f9cae0b613398b890867d64736f6c634300081e0033000000000000000000000000f4c259d287cc39e197b1148a198227472ca50b65000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e0000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb3254426400000000000000000000000000acc4d239aa05c797e038b7701be8be6940143900000000000000000000000012100faa7b157e9947340b44409fc7e27ec0abef
Deployed ByteCode
0x60806040526004361061017b575f3560e01c8063715018a6116100cd578063a834725a11610087578063e305333511610062578063e305333514610879578063e30c3978146108a5578063ea191743146108c2578063f2fde38b146108e1575f5ffd5b8063a834725a1461050d578063c3f909d41461052c578063df596d9e14610866575f5ffd5b8063715018a61461048157806379ba5097146104955780638456cb59146104a95780638abf6077146104bd5780638da5cb5b146104d15780639791e644146104ee575f5ffd5b806340df98661161013857806359db6e851161011357806359db6e85146102f95780635c975abb146103185780635ccc1718146103385780636aa6a01a1461036e575f5ffd5b806340df9866146102985780634f1ef286146102c457806352d1902d146102d7575f5ffd5b80630423c7de1461017f57806304f3bcec146101b957806319ab453c146101ff5780633075db56146102205780633659cfe6146102655780633f4ba83a14610284575b5f5ffd5b34801561018a575f5ffd5b5060fb5461019d9065ffffffffffff1681565b60405165ffffffffffff90911681526020015b60405180910390f35b3480156101c4575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020016101b0565b34801561020a575f5ffd5b5061021e610219366004613796565b610900565b005b34801561022b575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b60405190151581526020016101b0565b348015610270575f5ffd5b5061021e61027f366004613796565b610a12565b34801561028f575f5ffd5b5061021e610ad9565b3480156102a3575f5ffd5b506102b76102b23660046137c4565b610b34565b6040516101b091906137fb565b61021e6102d23660046139ab565b610b4b565b3480156102e2575f5ffd5b506102eb610c00565b6040519081526020016101b0565b348015610304575f5ffd5b5061021e610313366004613a50565b610cb1565b348015610323575f5ffd5b5061025560c954610100900460ff1660021490565b348015610343575f5ffd5b50610100546040805165ffffffffffff8084168252600160301b9093049092166020830152016101b0565b348015610379575f5ffd5b5061040e6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260fc5465ffffffffffff8082168352600160301b820481166020840152600160601b8204811693830193909352600160901b810483166060830152600160c01b9004909116608082015260fd5460a082015290565b6040516101b091905f60c08201905065ffffffffffff835116825265ffffffffffff602084015116602083015265ffffffffffff604084015116604083015265ffffffffffff606084015116606083015265ffffffffffff608084015116608083015260a083015160a083015292915050565b34801561048c575f5ffd5b5061021e610e63565b3480156104a0575f5ffd5b5061021e610e74565b3480156104b4575f5ffd5b5061021e610eeb565b3480156104c8575f5ffd5b506101e7610f40565b3480156104dc575f5ffd5b506033546001600160a01b03166101e7565b3480156104f9575f5ffd5b5061021e610508366004613aab565b610f4e565b348015610518575f5ffd5b506102eb610527366004613a50565b611064565b348015610537575f5ffd5b50610859604080516101e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c0810191909152604051806101e001604052807f00000000000000000000000012100faa7b157e9947340b44409fc7e27ec0abef6001600160a01b031681526020017f000000000000000000000000f4c259d287cc39e197b1148a198227472ca50b656001600160a01b031681526020017f000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e06001600160a01b031681526020017f000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb325442646001600160a01b031681526020017f00000000000000000000000000acc4d239aa05c797e038b7701be8be694014396001600160a01b031681526020017f0000000000000000000000000000000000000000000000000000000000001c2065ffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000b465ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000006481526020017f000000000000000000000000000000000000000000000000000000000000004b60ff1681526020017f000000000000000000000000000000000000000000000000000000000000000181526020017f000000000000000000000000000000000000000000000000000000000000000061ffff1681526020017f00000000000000000000000000000000000000000000000000000000009896806001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000326001600160401b031681526020017f000000000000000000000000000000000000000000000000000000000000018061ffff1681526020017f000000000000000000000000000000000000000000000000000000000000000560ff16815250905090565b6040516101b09190613b15565b61021e610874366004613ca1565b6110a7565b348015610884575f5ffd5b5061088d6111f9565b6040516001600160401b0390911681526020016101b0565b3480156108b0575f5ffd5b506065546001600160a01b03166101e7565b3480156108cd575f5ffd5b5061021e6108dc366004613aab565b6112c4565b3480156108ec575f5ffd5b5061021e6108fb366004613796565b6117c6565b5f54610100900460ff161580801561091e57505f54600160ff909116105b806109375750303b15801561093757505f5460ff166001145b61099f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff1916600117905580156109c0575f805461ff0019166101001790555b6109c982611837565b8015610a0e575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b037f000000000000000000000000ed704fbe2b64436d6a65a3f7b8c128a647ee97df163003610a5a5760405162461bcd60e51b815260040161099690613cf1565b7f000000000000000000000000ed704fbe2b64436d6a65a3f7b8c128a647ee97df6001600160a01b0316610a8c611895565b6001600160a01b031614610ab25760405162461bcd60e51b815260040161099690613d3d565b610abb816118b0565b604080515f80825260208201909252610ad6918391906118b8565b50565b610ae1611a22565b610af560c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a1610b32335f611a53565b565b6060610b4260ff8484611a5b565b90505b92915050565b6001600160a01b037f000000000000000000000000ed704fbe2b64436d6a65a3f7b8c128a647ee97df163003610b935760405162461bcd60e51b815260040161099690613cf1565b7f000000000000000000000000ed704fbe2b64436d6a65a3f7b8c128a647ee97df6001600160a01b0316610bc5611895565b6001600160a01b031614610beb5760405162461bcd60e51b815260040161099690613d3d565b610bf4826118b0565b610a0e828260016118b8565b5f306001600160a01b037f000000000000000000000000ed704fbe2b64436d6a65a3f7b8c128a647ee97df1614610c9f5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610996565b505f51602061437d5f395f51905f5290565b610cb9611c9e565b60fb54604051633dd0723360e21b81526004810183905265ffffffffffff90911660248201525f908190819081908190739c9d925f3d7d820a994811c17480fe67875a15629063f741c8cc906044015f60405180830381865af4158015610d22573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d499190810190614041565b60fb805465ffffffffffff191665ffffffffffff87811691909117909155845160fc80546020880151604089015160608a015160808b01519587166bffffffffffffffffffffffff1990941693909317600160301b92871692909202919091176bffffffffffffffffffffffff60601b1916600160601b9186169190910265ffffffffffff60901b191617600160901b918516919091021765ffffffffffff60c01b1916600160c01b929093169190910291909117905560a084015160fd55939850919650945092509050610e1e5f82611cf8565b610e288284611d42565b6040518681527fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d29060200160405180910390a1505050505050565b610e6b611c9e565b610b325f611d9a565b60655433906001600160a01b03168114610ee25760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610996565b610ad681611d9a565b610ef3611db3565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a1610b32336001611a53565b5f610f49611895565b905090565b610f56611de5565b610f606002611e2a565b5f610f9f83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250611e3392505050565b9050610faa81611e8b565b60fc5465ffffffffffff80821691600160301b8104821691600160601b9091041682610fe95760405163ba74d80f60e01b815260040160405180910390fd5b5f5f610ff9868b8b888888611ec7565b60fc80544365ffffffffffff908116600160301b026bffffffffffffffffffffffff1990921660018b019190911617179055815191935091506110449061103f84612168565b611cf8565b61104e8282611d42565b50505050505061105e6001611e2a565b50505050565b5f60fe816110927f000000000000000000000000000000000000000000000000000000000000006485614132565b81526020019081526020015f20549050919050565b60015f5260fe6020527f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b754806110f05760405163f37a8b1360e01b815260040160405180910390fd5b604080516312b2aa9160e31b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000989680811660248301527f0000000000000000000000000000000000000000000000000000000000000032166044820152835161ffff908116606483015260208501511660848201529083015162ffffff1660a48201525f90734c0dbff2abf9cbd7641cf38fc5765949a8e5b1bf9063959554889060c401602060405180830381865af41580156111be573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111e29190614151565b905080156111f4576111f433826121f9565b505050565b6040516343c3d71960e01b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000989680811660248301527f00000000000000000000000000000000000000000000000000000000000000321660448201525f90734c0dbff2abf9cbd7641cf38fc5765949a8e5b1bf906343c3d71990606401602060405180830381865af41580156112a0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f499190614168565b5f6112ce33612204565b6040805160c08101825260fc5465ffffffffffff8082168352600160301b82048116602080850191909152600160601b8304821684860152600160901b830482166060850152600160c01b90920416608083015260fd5460a08301528251601f8901829004820281018201909352878352929350915f916113689189908990819084018382808284375f9201919091525061230192505050565b80519091505f808061137a8685612471565b9250925092505f8165ffffffffffff165f146113c2578460c001516001830365ffffffffffff16815181106113b1576113b161418e565b6020026020010151606001516113c8565b84602001515b9050808760a00151146113ee5760405163198070b360e01b815260040160405180910390fd5b6113f783611064565b85604001511461141a5760405163f904c2fd60e01b815260040160405180910390fd5b87611429576114298583612542565b85602001518061146b57507f000000000000000000000000000000000000000000000000000000000000018061ffff1687608001510165ffffffffffff164210155b1561156a577f00000000000000000000000000acc4d239aa05c797e038b7701be8be694014396001600160a01b031663c9a0b8c86040518060600160405280886080015165ffffffffffff1681526020018860c0015160018903815181106114d5576114d561418e565b60200260200101516060015181526020018860a001518152506040518263ffffffff1660e01b815260040161152e9190815165ffffffffffff168152602080830151908201526040918201519181019190915260600190565b5f604051808303815f87803b158015611545575f5ffd5b505af1158015611557573d5f5f3e3d5ffd5b50505065ffffffffffff42166080890152505b65ffffffffffff80841660408901524216606088015260c085015180515f19860190811061159a5761159a61418e565b6020026020010151606001518760a00181815250508660fc5f820151815f015f6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506020820151815f0160066101000a81548165ffffffffffff021916908365ffffffffffff1602179055506040820151815f01600c6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506060820151815f0160126101000a81548165ffffffffffff021916908365ffffffffffff1602179055506080820151815f0160186101000a81548165ffffffffffff021916908365ffffffffffff16021790555060a082015181600101559050507fb2d5049ba96efb9e1fee66a51e4e6cbdfa2949627891ee29c6e4281abb8da03c6116c7604051806020016040528089815250612748565b6040516116d491906141d0565b60405180910390a15f61172d886060015165ffffffffffff168760c001518565ffffffffffff168151811061170b5761170b61418e565b60200260200101516040015165ffffffffffff1661287290919063ffffffff16565b420390507f000000000000000000000000f4c259d287cc39e197b1148a198227472ca50b656001600160a01b03166314bcf3dd8261176a89612887565b8e8e6040518563ffffffff1660e01b815260040161178b949392919061420a565b5f6040518083038186803b1580156117a1575f5ffd5b505afa1580156117b3573d5f5f3e3d5ffd5b5050505050505050505050505050505050565b6117ce611c9e565b606580546001600160a01b0383166001600160a01b031990911681179091556117ff6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f54610100900460ff1661185d5760405162461bcd60e51b815260040161099690614229565b6118656129de565b6118836001600160a01b0382161561187d5781611d9a565b33611d9a565b5060c9805461ff001916610100179055565b5f51602061437d5f395f51905f52546001600160a01b031690565b610ad6611c9e565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156118eb576111f483612a04565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611945575060408051601f3d908101601f1916820190925261194291810190614151565b60015b6119a85760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610996565b5f51602061437d5f395f51905f528114611a165760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610996565b506111f4838383612a9f565b611a3660c954610100900460ff1660021490565b610b325760405163bae6e2a960e01b815260040160405180910390fd5b610a0e611c9e565b600183015460609065ffffffffffff80821691600160301b90048116908516821180611a9757508065ffffffffffff168565ffffffffffff1610155b80611aa8575065ffffffffffff8416155b15611b1157604080515f8082526020820190925290611b07565b611af46040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b815260200190600190039081611ac25790505b5092505050611c97565b5f611b2965ffffffffffff8784038116908716612ac3565b9050806001600160401b03811115611b4357611b436138d9565b604051908082528060200260200182016040528015611ba657816020015b611b936040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b815260200190600190039081611b615790505b5093505f5b81811015611c925765ffffffffffff871681015f90815260208981526040918290208251808401845281546001600160401b0316815283516001830180546080818702840181019097526060830181815293969495870194929391928492918491840182828015611c3957602002820191905f5260205f20905b815481526020019060010190808311611c25575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff166040909101529052508551869083908110611c7f57611c7f61418e565b6020908102919091010152600101611bab565b505050505b9392505050565b6033546001600160a01b03163314610b325760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610996565b8060fe5f611d2e7f000000000000000000000000000000000000000000000000000000000000006465ffffffffffff8716614132565b815260208101919091526040015f20555050565b60408051808201909152828152602081018290527f10b2060c55406ea48522476f67fd813d4984b12078555d3e2a377e35839d7d01611d8082612ad7565b604051611d8d91906141d0565b60405180910390a1505050565b606580546001600160a01b0319169055610ad681612cb1565b611dc760c954610100900460ff1660021490565b15610b325760405163bae6e2a960e01b815260040160405180910390fd5b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff1603610b325760405163dfc60d8560e01b815260040160405180910390fd5b610ad681612d02565b611e3b6136ed565b60208281015160d01c82526026830151828201805160f092831c905260288501518151921c9190920152602a830151905160e89190911c604091820152602d9092015160f81c9181019190915290565b805165ffffffffffff161580611eaa5750805165ffffffffffff164211155b610ad65760405163559895a360e01b815260040160405180910390fd5b6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152604080516080810182525f80825260208201819052918101919091526060808201528365ffffffffffff164311611f42576040516349517a1d60e11b815260040160405180910390fd5b5f611f7d868590035f1990810165ffffffffffff167f0000000000000000000000000000000000000000000000000000000000000064030190565b11611f9b5760405163eaabac9b60e01b815260040160405180910390fd5b5f611fad338a6040015160ff16612d28565b905060405180604001604052805f15158152602001611fcf8b60200151612eee565b9052815180515f198101908110611fe857611fe861418e565b60200260200101819052505f816020015161209257604051635600026d60e11b81526001600160a01b037f000000000000000000000000638f73a482478130bea16ce151e48aec0ab283e0169063ac0004da9061204d9033908d908d90600401614274565b6020604051808303815f875af1158015612069573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061208d91906142a1565b612094565b5f5b90505f60014303905060405180608001604052808265ffffffffffff168152602001824081526020017f000000000000000000000000000000000000000000000000000000000000004b60ff168152602001845f015181525093506040518060c001604052808965ffffffffffff1681526020014265ffffffffffff1681526020018365ffffffffffff168152602001336001600160a01b0316815260200161214760018b0365ffffffffffff16611064565b81526020016121558661302f565b8152509450505050965096945050505050565b604080516006815260e08101909152815165ffffffffffff1660208201525f90602083015165ffffffffffff166040820152604083015165ffffffffffff16606082015260608301516001600160a01b03166080820152608083015160a082015260a083015160c0820152805160051b6020820120611c978280516040516001820160051b83011490151060061b52565b610a0e82825a613234565b5f7f000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb325442646001600160a01b031661223a57505f919050565b604051633326844b60e11b81526001600160a01b0383811660048301525f9182917f000000000000000000000000bb128fd4942e8143b8dc10f38ccfeadb32544264169063664d0896906024016040805180830381865afa1580156122a1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122c591906142bc565b91509150805f036122d957505f9392505050565b816122f75760405163c1a58f1960e01b815260040160405180910390fd5b5060019392505050565b612309613724565b602082810151825160d091821c90526026840151835190920191909152604683015182516040015260668301518251606091821c910152607a8301518251911c608091820152820151815160a09081019190915282015160a283019060f01c806001600160401b03811115612380576123806138d9565b6040519080825280602002602001820160405280156123d057816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161239e5790505b50835160c001525f5b8161ffff1681101561245f57604080516080810182525f8082526020820181815292820181815260608084019283528751811c84526014880151901c909352602886015160d01c909252602e850151909152604e8401855160c001518051849081106124475761244761418e565b602090810291909101019190915292506001016123d9565b50505160f81c15156020820152919050565b604082015160c082015151905f90819060010165ffffffffffff16836124aa5760405163c2e5347d60e01b815260040160405180910390fd5b845165ffffffffffff168110156124d4576040516363db3a4160e01b815260040160405180910390fd5b845186515f1965ffffffffffff92831687010194501683106125095760405163677c56f160e01b815260040160405180910390fd5b8083101561252a5760405163181432e760e11b815260040160405180910390fd5b845f015165ffffffffffff1681039150509250925092565b5f6125e97f00000000000000000000000000000000000000000000000000000000000000b460fc5f0160129054906101000a900465ffffffffffff160165ffffffffffff167f0000000000000000000000000000000000000000000000000000000000001c208560c001518565ffffffffffff16815181106125c6576125c661418e565b6020026020010151604001510165ffffffffffff1661287290919063ffffffff16565b90508042116125f757505050565b60408051608081019091528351830165ffffffffffff1681525f9060208101600181526020018560c001518565ffffffffffff168151811061263b5761263b61418e565b6020026020010151602001516001600160a01b0316815260200185606001516001600160a01b031681525090507f00000000000000000000000000acc4d239aa05c797e038b7701be8be694014396001600160a01b03166366ca2bc06126a083613277565b6040518263ffffffff1660e01b81526004016126be91815260200190565b6020604051808303815f875af11580156126da573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126fe9190614151565b50805f015165ffffffffffff167f8796b99bbf275a983988181e85b42502d9347327f4dde674320bec3879bcc5e18260405161273a91906142e6565b60405180910390a250505050565b80515160c08101515160609190604e02608301806001600160401b03811115612773576127736138d9565b6040519080825280601f01601f19166020018201604052801561279d576020820181803683370190505b50825160d090811b602083810191909152840151602683015260408401516046830152606080850151901b606683015260808085015190911b607a83015260a0808501519183019190915260c0840151519194508401906127fd906132a6565b60c08301515160f01b81526002015f5b8360c001515181101561284b57612841828560c0015183815181106128345761283461418e565b60200260200101516132c9565b915060010161280d565b5061286981865f015160200151612862575f6132fe565b60016132fe565b50505050919050565b5f8183116128805781610b42565b5090919050565b60c081015180515f919060096004820201836128b38260408051828152600190920160051b8201905290565b6020808201529050855165ffffffffffff166040820152602086015160608201526040860151608082015260608601516001600160a01b031660a0820152608086015165ffffffffffff1660c082015260a086015160e082015260e0610100820152610120810183905260095f5b848110156129ac575f86828151811061293c5761293c61418e565b602090810291909101015180516001600160a01b03166001850160051b860152905060208101516001600160a01b03166002840160051b850152604081015165ffffffffffff166003840160051b85015260608101516004840160051b8501525060049190910190600101612921565b50815160051b60208301206129d38380516040516001820160051b83011490151060061b52565b979650505050505050565b5f54610100900460ff16610b325760405162461bcd60e51b815260040161099690614229565b6001600160a01b0381163b612a715760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610996565b5f51602061437d5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b612aa88361330a565b5f82511180612ab45750805b156111f45761105e8383613349565b5f818311612ad15782610b42565b50919050565b60605f612aeb83602001516060015161336e565b9050806001600160401b03811115612b0557612b056138d9565b6040519080825280601f01601f191660200182016040528015612b2f576020820181803683370190505b5083515160d090811b6020838101919091528551606090810151901b60268401528551810151821b603a8401528551604090810151831b81850152865160800151604685015281870180515190931b6066850152825190910151606c84015290510151909250608c830190612ba59082906132fe565b60208501516060015151909150612bbb816132a6565b612bcb828260f01b815260020190565b91505f5b81811015612ca1575f8660200151606001518281518110612bf257612bf261418e565b60200260200101519050612c0e84825f0151612862575f6132fe565b60208201515151909450612c21816132a6565b612c31858260f01b815260020190565b94505f5b81811015612c7457612c6a8684602001515f01518381518110612c5a57612c5a61418e565b6020026020010151815260200190565b9550600101612c35565b5050602090810180519091015160e81b8452516040015160d01b6003840152600990920191600101612bcf565b5050925160a00151909252919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60408051808201909152606081525f60208201526101005460ff9065ffffffffffff80821691600160301b9004811690828203165f818711612d6a5786612d6c565b815b9050806001016001600160401b03811115612d8957612d896138d9565b604051908082528060200260200182016040528015612dec57816020015b612dd96040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b815260200190600190039081612da75790505b508087525f90612e019087908b9088866133b2565b955090507f000000000000000000000000000000000000000000000000000000000000000188108015612e3357508183115b15612e88575f612e658787877f0000000000000000000000000000000000000000000000000000000000000000613536565b90508015612e865760405163014b3fdb60e11b815260040160405180910390fd5b505b65ffffffffffff167f000000000000000000000000000000000000000000000000000000000000000560ff167f000000000000000000000000000000000000000000000000000000000000000061ffff1602014211602087015250939695505050505050565b604080516060808201835281525f6020808301829052928201529082015161ffff16612f2d5760405163fdac229f60e01b815260040160405180910390fd5b5f826020015161ffff166001600160401b03811115612f4e57612f4e6138d9565b604051908082528060200260200182016040528015612f77578160200160208202803683370190505b5090505f5b836020015161ffff16811015612fff578351612f9d90829061ffff16614347565b49828281518110612fb057612fb061418e565b602002602001018181525050818181518110612fce57612fce61418e565b60200260200101515f5f1b03612ff757604051637bb2fa2f60e11b815260040160405180910390fd5b600101612f7c565b50604080516060810182529182529283015162ffffff16602082015265ffffffffffff4216928101929092525090565b606081015180515f919060068101835b8281101561307b578381815181106130595761305961418e565b6020026020010151602001515f0151516006018201915080600101905061303f565b50604080518281526001830160051b8101909152602080820152855165ffffffffffff16604082015260208601516060820152604086015160ff166080820152608060a082015260c0810183905260068381015f5b85811015613201575f8782815181106130eb576130eb61418e565b60200260200101519050613114858386016005878703901b5f1b60019190910160051b82015290565b5061313d8584835f0151613128575f61312b565b60015b60ff1660019190910160051b82015290565b5060406002840160051b86015260606003840160051b86015260028301602080830151015162ffffff166002820160051b87015260208201516040015165ffffffffffff166003820160051b87015260208201515180516004830160051b8801819052600383015f5b828110156131ea576131e18a8284600101018684815181106131ca576131ca61418e565b602002602001015160019190910160051b82015290565b506001016131a6565b5001600190810195509390930192506130d0915050565b50825160051b60208401206132288480516040516001820160051b83011490151060061b52565b98975050505050505050565b815f0361324057505050565b61325a83838360405180602001604052805f81525061359f565b6111f457604051634c67134d60e11b815260040160405180910390fd5b5f8160405160200161328991906142e6565b604051602081830303815290604052805190602001209050919050565b61ffff811115610ad65760405163161e7a6b60e11b815260040160405180910390fd5b8051606090811b83526020820151811b6014840152604082015160d01b6028840152810151602e8301908152604e8301610b42565b5f818353505060010190565b61331381612a04565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b42838360405180606001604052806027815260200161439d602791396135dc565b608f5f5b8251811015612ad15782818151811061338d5761338d61418e565b6020026020010151602001515f015151602002600c0182019150806001019050613372565b5f5f825f036133cb575065ffffffffffff90508261352c565b5f5f5b848110156134bb5765ffffffffffff861681015f90815260208a81526040918290208251808401845260018082528451908301805460808187028401810190975260608301818152949693958601949293919284929091849184018282801561345457602002820191905f5260205f20905b815481526020019060010190808311613440575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff16604090910152905288518990849081106134995761349961418e565b6020908102919091010152546001600160401b031691909101906001016133ce565b5080156134db576134db6001600160a01b038816633b9aca0083026121f9565b855f815181106134ed576134ed61418e565b602002602001015160200151604001519250838501915081886001015f6101000a81548165ffffffffffff021916908365ffffffffffff160217905550505b9550959350505050565b5f8265ffffffffffff168465ffffffffffff160361355557505f613597565b65ffffffffffff8085165f90815260208790526040812060020154630100000090049091169081900361358b575f915050613597565b61ffff83160142101590505b949350505050565b5f6001600160a01b0385166135c757604051634c67134d60e11b815260040160405180910390fd5b5f5f835160208501878988f195945050505050565b60605f5f856001600160a01b0316856040516135f89190614366565b5f60405180830381855af49150503d805f8114613630576040519150601f19603f3d011682016040523d82523d5f602084013e613635565b606091505b509150915061364686838387613650565b9695505050505050565b606083156136be5782515f036136b7576001600160a01b0385163b6136b75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610996565b5081613597565b61359783838151156136d35781518083602001fd5b8060405162461bcd60e51b815260040161099691906141d0565b60408051606080820183525f8083528351918201845280825260208281018290529382015290918201905b81525f60209091015290565b60405180604001604052806137186040518060e001604052805f65ffffffffffff1681526020015f81526020015f81526020015f6001600160a01b031681526020015f65ffffffffffff1681526020015f8152602001606081525090565b6001600160a01b0381168114610ad6575f5ffd5b5f602082840312156137a6575f5ffd5b8135611c9781613782565b65ffffffffffff81168114610ad6575f5ffd5b5f5f604083850312156137d5575f5ffd5b82356137e0816137b1565b915060208301356137f0816137b1565b809150509250929050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156138cd57868503603f19018452815180516001600160401b0316865260209081015160408288018190528151606091890191909152805160a08901819052919201905f9060c08901905b80831015613892578351825260208201915060208401935060018301925061386f565b5060208481015162ffffff1660608b015260409094015165ffffffffffff166080909901989098525050938401939190910190600101613821565b50929695505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561390f5761390f6138d9565b60405290565b604051608081016001600160401b038111828210171561390f5761390f6138d9565b604080519081016001600160401b038111828210171561390f5761390f6138d9565b60405160c081016001600160401b038111828210171561390f5761390f6138d9565b604051601f8201601f191681016001600160401b03811182821017156139a3576139a36138d9565b604052919050565b5f5f604083850312156139bc575f5ffd5b82356139c781613782565b915060208301356001600160401b038111156139e1575f5ffd5b8301601f810185136139f1575f5ffd5b80356001600160401b03811115613a0a57613a0a6138d9565b613a1d601f8201601f191660200161397b565b818152866020838501011115613a31575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f60208284031215613a60575f5ffd5b5035919050565b5f5f83601f840112613a77575f5ffd5b5081356001600160401b03811115613a8d575f5ffd5b602083019150836020828501011115613aa4575f5ffd5b9250929050565b5f5f5f5f60408587031215613abe575f5ffd5b84356001600160401b03811115613ad3575f5ffd5b613adf87828801613a67565b90955093505060208501356001600160401b03811115613afd575f5ffd5b613b0987828801613a67565b95989497509550505050565b81516001600160a01b031681526101e081016020830151613b4160208401826001600160a01b03169052565b506040830151613b5c60408401826001600160a01b03169052565b506060830151613b7760608401826001600160a01b03169052565b506080830151613b9260808401826001600160a01b03169052565b5060a0830151613bac60a084018265ffffffffffff169052565b5060c0830151613bc660c084018265ffffffffffff169052565b5060e083015160e0830152610100830151613be761010084018260ff169052565b50610120830151610120830152610140830151613c0b61014084018261ffff169052565b50610160830151613c286101608401826001600160401b03169052565b50610180830151613c456101808401826001600160401b03169052565b506101a0830151613c5d6101a084018261ffff169052565b506101c0830151613c746101c084018260ff169052565b5092915050565b803561ffff81168114613c8c575f5ffd5b919050565b62ffffff81168114610ad6575f5ffd5b5f6060828403128015613cb2575f5ffd5b50613cbb6138ed565b613cc483613c7b565b8152613cd260208401613c7b565b60208201526040830135613ce581613c91565b60408201529392505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b8051613c8c816137b1565b5f6001600160401b03821115613dac57613dac6138d9565b5060051b60200190565b80518015158114613c8c575f5ffd5b8051613c8c81613c91565b5f60808284031215613de0575f5ffd5b613de8613915565b90508151613df5816137b1565b815260208281015190820152604082015160ff81168114613e14575f5ffd5b604082015260608201516001600160401b03811115613e31575f5ffd5b8201601f81018413613e41575f5ffd5b8051613e54613e4f82613d94565b61397b565b8082825260208201915060208360051b850101925086831115613e75575f5ffd5b602084015b83811015613fb55780516001600160401b03811115613e97575f5ffd5b85016040818a03601f19011215613eac575f5ffd5b613eb4613937565b613ec060208301613db6565b815260408201516001600160401b03811115613eda575f5ffd5b6020818401019250506060828b031215613ef2575f5ffd5b613efa6138ed565b82516001600160401b03811115613f0f575f5ffd5b8301601f81018c13613f1f575f5ffd5b8051613f2d613e4f82613d94565b8082825260208201915060208360051b85010192508e831115613f4e575f5ffd5b6020840193505b82841015613f70578351825260209384019390910190613f55565b845250613f8291505060208401613dc5565b6020820152613f9360408401613d89565b6040820152806020830152508085525050602083019250602081019050613e7a565b5060608501525091949350505050565b5f60c08284031215613fd5575f5ffd5b613fdd613959565b90508151613fea816137b1565b81526020820151613ffa816137b1565b6020820152604082015161400d816137b1565b6040820152606082015161402081613782565b60608201526080828101519082015260a09182015191810191909152919050565b5f5f5f5f5f8587036101e0811215614057575f5ffd5b8651614062816137b1565b955060c0601f1982011215614075575f5ffd5b5061407e613959565b602087015161408c816137b1565b8152604087015161409c816137b1565b602082015260608701516140af816137b1565b604082015260808701516140c2816137b1565b606082015260a08701516140d5816137b1565b608082015260c087015160a082015260e08701519094506001600160401b038111156140ff575f5ffd5b61410b88828901613dd0565b93505061411c876101008801613fc5565b6101c09690960151949793965091949392915050565b5f8261414c57634e487b7160e01b5f52601260045260245ffd5b500690565b5f60208284031215614161575f5ffd5b5051919050565b5f60208284031215614178575f5ffd5b81516001600160401b0381168114611c97575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610b4260208301846141a2565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b848152836020820152606060408201525f6136466060830184866141e2565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03841681526040602082018190525f9061429890830184866141e2565b95945050505050565b5f602082840312156142b1575f5ffd5b8151611c97816137b1565b5f5f604083850312156142cd575f5ffd5b6142d683613db6565b6020939093015192949293505050565b815165ffffffffffff168152602082015160808201906002811061431857634e487b7160e01b5f52602160045260245ffd5b60208301526040838101516001600160a01b039081169184019190915260609384015116929091019190915290565b80820180821115610b4557634e487b7160e01b5f52601160045260245ffd5b5f82518060208501845e5f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d4f1ac9fd49ea7eee6187da54098c4e23fef4ba2c14f9cae0b613398b890867d64736f6c634300081e0033