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
- 2026-01-09T13:04:29.831894Z
Constructor Arguments
0x000000000000000000000000461461e95de3cc306d5424f554463c162433384e000000000000000000000000cfb57e95cbab87bfd167b3eddd5c11e2d1613b2200000000000000000000000053789e39e3310737e8c8ced483032aac25b39ded000000000000000000000000cbf1639b8809adff74bd59ec292e436107852cc9000000000000000000000000a20182131658295f37c1a1efdbdc89eff97d9c58000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Arg [0] (address) : 0x461461e95de3cc306d5424f554463c162433384e
Arg [1] (address) : 0xcfb57e95cbab87bfd167b3eddd5c11e2d1613b22
Arg [2] (address) : 0x53789e39e3310737e8c8ced483032aac25b39ded
Arg [3] (address) : 0xcbf1639b8809adff74bd59ec292e436107852cc9
Arg [4] (address) : 0xa20182131658295f37c1a1efdbdc89eff97d9c58
Arg [5] (uint64) : 0
Arg [6] (uint64) : 0
Arg [7] (uint48) : 0
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 _bondToken,
uint64 _minBond,
uint64 _livenessBond,
uint48 _withdrawalDelay
)
Inbox(Config({
proofVerifier: _proofVerifier,
proposerChecker: _proposerChecker,
proverWhitelist: _proverWhitelist,
signalService: _signalService,
bondToken: _bondToken,
minBond: _minBond,
livenessBond: _livenessBond,
withdrawalDelay: _withdrawalDelay,
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();
}
}
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/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/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_);
}
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/core/libs/LibBlobs.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/// @title LibBlobs
/// @notice Library for handling blobs.
/// @custom:security-contact security@taiko.xyz
library LibBlobs {
/// @notice Represents a segment of data that is stored in multiple consecutive blobs created
/// in this transaction.
struct BlobReference {
/// @notice The starting index of the blob.
uint16 blobStartIndex;
/// @notice The number of blobs.
uint16 numBlobs;
/// @notice The field-element offset within the blob data.
uint24 offset;
}
/// @notice Represents a frame of data that is stored in multiple blobs. Note the size is
/// encoded as a bytes32 at the offset location.
struct BlobSlice {
/// @notice The blobs containing the proposal's content.
bytes32[] blobHashes;
/// @notice The byte offset of the proposal's content in the containing blobs.
uint24 offset;
/// @notice The timestamp when the frame was created.
uint48 timestamp;
}
// ---------------------------------------------------------------
// Functions
// ---------------------------------------------------------------
/// @dev Validates a blob locator and converts it to a blob slice.
/// @param _blobReference The blob locator to validate.
/// @return The blob slice.
function validateBlobReference(BlobReference memory _blobReference)
internal
view
returns (BlobSlice memory)
{
require(_blobReference.numBlobs > 0, NoBlobs());
bytes32[] memory blobHashes = new bytes32[](_blobReference.numBlobs);
for (uint256 i; i < _blobReference.numBlobs; ++i) {
blobHashes[i] = blobhash(_blobReference.blobStartIndex + i);
require(blobHashes[i] != 0, BlobNotFound());
}
return BlobSlice({
blobHashes: blobHashes,
offset: _blobReference.offset,
timestamp: uint48(block.timestamp)
});
}
// ---------------------------------------------------------------
// Errors
// ---------------------------------------------------------------
error BlobNotFound();
error NoBlobs();
}
contracts/shared/signal/ISignalService.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "./ICheckpointStore.sol";
/// @title ISignalService
/// @notice The SignalService contract serves as a secure cross-chain message
/// passing system. It defines methods for sending and verifying signals with
/// merkle proofs. The trust assumption is that the target chain has secure
/// access to the merkle root (such as Taiko injects it in the anchor
/// transaction). With this, verifying a signal is reduced to simply verifying
/// a merkle proof.
/// @custom:security-contact security@taiko.xyz
interface ISignalService is ICheckpointStore {
/// @dev DEPRECATED
/// @dev Caching is no longer supported
enum CacheOption {
CACHE_NOTHING,
CACHE_SIGNAL_ROOT,
CACHE_STATE_ROOT,
CACHE_BOTH
}
struct HopProof {
/// @notice This hop's destination chain ID. If there is a next hop, this ID is the next
/// hop's source chain ID.
uint64 chainId;
/// @notice The ID of a source chain block whose state root has been synced to the hop's
/// destination chain.
/// Note that this block ID must be greater than or equal to the block ID where the signal
/// was sent on the source chain.
uint64 blockId;
/// @notice The state root or signal root of the source chain at the above blockId. This
/// value has been synced to the destination chain.
/// @dev To get both the blockId and the rootHash, apps should subscribe to the
/// ChainDataSynced event or query `topBlockId` first using the source chain's ID and
/// LibStrings.H_STATE_ROOT to get the most recent block ID synced, then call
/// `getSyncedChainData` to read the synchronized data.
bytes32 rootHash;
/// @notice Options to cache either the state roots or signal roots of middle-hops to the
/// current chain.
/// @dev DEPRECATED - this value will be ignored
CacheOption cacheOption;
/// @notice The signal service's account proof. If this value is empty, then `rootHash` will
/// be used as the signal root, otherwise, `rootHash` will be used as the state root.
bytes[] accountProof;
/// @notice The signal service's storage proof.
bytes[] storageProof;
}
/// @notice Emitted when a signal is sent.
/// @param app The address that initiated the signal.
/// @param signal The signal (message) that was sent.
/// @param slot The location in storage where this signal is stored.
/// @param value The value of the signal.
event SignalSent(address app, bytes32 signal, bytes32 slot, bytes32 value);
/// @notice Send a signal (message) by setting the storage slot to the same value as the signal
/// itself.
/// @param _signal The signal (message) to send.
/// @return slot_ The location in storage where this signal is stored.
function sendSignal(bytes32 _signal) external returns (bytes32 slot_);
/// @notice Checks whether a signal has been received on the target chain and caches the result if successful.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain. If this proof is empty, then we check if this signal has been marked as
/// received by TaikoL2.
/// @return numCacheOps_ The number of newly cached items.
function proveSignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
returns (uint256 numCacheOps_);
/// @notice Verifies if a signal has been received on the target chain.
/// This is the "readonly" version of proveSignalReceived.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain. If this proof is empty, then we check if this signal has been marked as
/// received by TaikoL2.
function verifySignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
view;
/// @notice Verifies if a particular signal has already been sent.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) that was sent.
/// @return true if the signal has been sent, otherwise false.
function isSignalSent(address _app, bytes32 _signal) external view returns (bool);
/// @notice Verifies if a particular signal has already been sent.
/// @param _signalSlot The location in storage where this signal is stored.
function isSignalSent(bytes32 _signalSlot) external view returns (bool);
}
contracts/layer1/core/iface/IProposerChecker.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProposerChecker
/// @notice Interface for checking if an address is authorized to propose blocks
/// @custom:security-contact security@taiko.xyz
interface IProposerChecker {
error InvalidProposer();
/// @notice Checks if an address is a valid proposer
/// @param _proposer The address to check
/// @param _lookaheadData Encoded lookahead metadata used by preconf-aware proposer checkers.
/// @return endOfSubmissionWindowTimestamp_ The timestamp of the last slot where the current
/// preconfer can propose.
/// @dev This function must revert if the address is not a valid proposer
function checkProposer(
address _proposer,
bytes calldata _lookaheadData
)
external
returns (uint48 endOfSubmissionWindowTimestamp_);
}
node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
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.26;
/// @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
// _bondStorage | struct LibBonds.Storage | Slot: 257 | Offset: 0 | Bytes: 32
// __gap | uint256[43] | Slot: 258 | Offset: 0 | Bytes: 1376
contracts/layer1/core/iface/IProverWhitelist.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProverWhitelist
/// @notice Interface for checking if an address is authorized to prove blocks
/// @custom:security-contact security@taiko.xyz
interface IProverWhitelist {
/// @notice Checks if an address is a whitelisted prover
/// @param _prover The address to check
/// @return isWhitelisted_ True if the address is whitelisted, false otherwise
/// @return proverCount_ The total number of whitelisted provers
function isProverWhitelisted(address _prover)
external
view
returns (bool isWhitelisted_, uint256 proverCount_);
}
contracts/layer1/core/iface/IBondManager.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/// @title IBondManager
/// @notice Interface for managing bonds on L1 in the Taiko protocol.
/// @custom:security-contact security@taiko.xyz
interface IBondManager {
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @notice Represents a bond for a given address.
struct Bond {
/// @notice The bond balance in gwei.
uint64 balance;
/// @notice The timestamp when the withdrawal was requested.
/// @dev 0 = active, >0 = withdrawal requested timestamp
uint48 withdrawalRequestedAt;
}
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
/// @notice Emitted when a bond is deposited.
/// @param depositor The account that made the deposit.
/// @param recipient The account that received the bond credit.
/// @param amount The amount deposited in gwei.
event BondDeposited(address indexed depositor, address indexed recipient, uint64 amount);
/// @notice Emitted when a bond is withdrawn.
/// @param account The account that withdrew the bond.
/// @param amount The amount withdrawn in gwei.
event BondWithdrawn(address indexed account, uint64 amount);
/// @notice Emitted when a withdrawal is requested.
/// @param account The account requesting withdrawal.
/// @param withdrawableAt The timestamp when withdrawal becomes unrestricted.
event WithdrawalRequested(address indexed account, uint48 withdrawableAt);
/// @notice Emitted when a withdrawal request is cancelled.
/// @param account The account cancelling the withdrawal request.
event WithdrawalCancelled(address indexed account);
/// @notice Emitted when a liveness bond is settled.
/// @param payer The account that paid the liveness bond.
/// @param payee The account that received the liveness bond.
/// @param livenessBond The value of the liveness bond in gwei.
/// @param credited The amount of the liveness bond that was credited to the payee in gwei.
/// @param slashed The amount of the liveness bond that was slashed in gwei.
event LivenessBondSettled(
address indexed payer,
address indexed payee,
uint64 livenessBond,
uint64 credited,
uint64 slashed
);
// ---------------------------------------------------------------
// Transactional Functions
// ---------------------------------------------------------------
/// @notice Deposits bond tokens for the caller.
/// @dev Clears the caller's pending withdrawal request, if any.
/// @param _amount The amount to deposit in gwei.
function deposit(uint64 _amount) external;
/// @notice Deposits bond tokens for a recipient.
/// @dev Recipient must be non-zero. Does not cancel the recipient's pending withdrawal,
/// even if the recipient is the caller.
/// @param _recipient The address to credit the bond to.
/// @param _amount The amount to deposit in gwei.
function depositTo(address _recipient, uint64 _amount) external;
/// @notice Withdraws bond to a recipient.
/// @dev Withdrawals are subject to a delay so bond operations can be resolved properly.
/// The user can always withdraw any excess amount without delays.
/// If this withdrawal debits the entire bond balance, any pending withdrawal request is
/// cleared.
/// @param _to The recipient of withdrawn funds.
/// @param _amount The amount to withdraw in gwei.
function withdraw(address _to, uint64 _amount) external;
/// @notice Requests to start the withdrawal process.
/// @dev Account cannot perform bond-restricted actions after requesting withdrawal.
function requestWithdrawal() external;
/// @notice Cancels withdrawal request to reactivate the account.
/// @dev Can be called during or after the withdrawal delay period.
function cancelWithdrawal() external;
// ---------------------------------------------------------------
// View Functions
// ---------------------------------------------------------------
/// @notice Gets the bond state of an address.
/// @param _address The address to get the bond state for.
/// @return bond_ The bond struct for the address.
function getBond(address _address) external view returns (Bond memory bond_);
}
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(when more efficient than keccak256)
/// @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(when more efficient than keccak256).
/// @custom:security-contact security@taiko.xyz
library LibHashOptimized {
// ---------------------------------------------------------------
// Core Structure Hashing Functions
// ---------------------------------------------------------------
/// @notice Hashing for proposal data.
/// @dev Uses keccak256(abi.encode(...)) to hash the proposal. Contrarty to the intuition,
/// this is as efficient if not more than using `EfficientHashLib` in this case because
/// the structure of the data(nested dynamic arryas).
/// @param _proposal The proposal to hash
/// @return The hash of the proposal
function hashProposal(IInbox.Proposal memory _proposal) internal pure returns (bytes32) {
/// forge-lint: disable-start(asm-keccak256)
return keccak256(abi.encode(_proposal));
}
/// @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 (3 words each)
uint256 totalWords = 9 + transitionsLength * 3;
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(transition.timestamp)));
EfficientHashLib.set(buffer, base + 2, transition.blockHash);
base += 3;
}
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/libs/LibBonds.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { IBondManager } from "../iface/IBondManager.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/// @title LibBonds
/// @notice Library for bond ledger operations and settlement.
/// @custom:security-contact security@taiko.xyz
library LibBonds {
using SafeERC20 for IERC20;
// ---------------------------------------------------------------
// Constants
// ---------------------------------------------------------------
uint256 internal constant GWEI_UNIT = 1 gwei;
// ---------------------------------------------------------------
// Storage
// ---------------------------------------------------------------
/// @dev Storage layout for bond balances. Each bond packs into one slot.
struct Storage {
mapping(address account => IBondManager.Bond bond) bonds;
}
// ---------------------------------------------------------------
// Internal Functions meant to be called by contracts that use this library
// ---------------------------------------------------------------
/// @dev Deposits bond tokens in gwei units and credits the recipient.
/// If `_cancelWithdrawal` is true, the pending withdrawal request is cleared.
function deposit(
Storage storage $,
IERC20 _bondToken,
address _depositor,
address _recipient,
uint64 _amount,
bool _cancelWithdrawal
)
internal
{
if (_recipient == address(0)) revert InvalidAddress();
_creditBond($, _recipient, _amount);
if (_cancelWithdrawal && $.bonds[_recipient].withdrawalRequestedAt != 0) {
$.bonds[_recipient].withdrawalRequestedAt = 0;
}
_bondToken.safeTransferFrom(_depositor, address(this), _toTokenAmount(_amount));
emit IBondManager.BondDeposited(_depositor, _recipient, _amount);
}
/// @dev Withdraws bond tokens in gwei units to a recipient.
/// If the full balance is withdrawn, the pending withdrawal request is cleared.
function withdraw(
Storage storage $,
IERC20 _bondToken,
address _from,
address _to,
uint64 _amount,
uint64 _minBond,
uint48 _withdrawalDelay
)
internal
returns (uint64 debited_)
{
if (_to == address(0)) revert InvalidAddress();
IBondManager.Bond storage bond_ = $.bonds[_from];
uint64 balance = bond_.balance;
uint64 amount = _amount > balance ? balance : _amount;
if (
bond_.withdrawalRequestedAt == 0
|| block.timestamp < bond_.withdrawalRequestedAt + _withdrawalDelay
) {
require(balance - amount >= _minBond, MustMaintainMinBond());
}
debited_ = _debitBond($, _from, amount);
if (debited_ == balance && bond_.withdrawalRequestedAt != 0) {
bond_.withdrawalRequestedAt = 0;
}
_bondToken.safeTransfer(_to, _toTokenAmount(debited_));
emit IBondManager.BondWithdrawn(_from, debited_);
}
/// @dev Requests a withdrawal. Withdrawals are unrestricted after the delay.
function requestWithdrawal(
Storage storage $,
address _account,
uint48 _withdrawalDelay
)
internal
{
IBondManager.Bond memory bond_ = $.bonds[_account];
if (bond_.balance == 0) revert NoBondToWithdraw();
if (bond_.withdrawalRequestedAt != 0) revert WithdrawalAlreadyRequested();
bond_.withdrawalRequestedAt = uint48(block.timestamp);
$.bonds[_account] = bond_;
emit IBondManager.WithdrawalRequested(_account, uint48(block.timestamp + _withdrawalDelay));
}
/// @dev Cancels a pending withdrawal request.
function cancelWithdrawal(Storage storage $, address _account) internal {
IBondManager.Bond storage bond_ = $.bonds[_account];
if (bond_.withdrawalRequestedAt == 0) revert NoWithdrawalRequested();
bond_.withdrawalRequestedAt = 0;
emit IBondManager.WithdrawalCancelled(_account);
}
/// @dev Returns the bond state for an account.
function getBond(
Storage storage $,
address _account
)
internal
view
returns (IBondManager.Bond memory)
{
return $.bonds[_account];
}
/// @dev Checks if an account has sufficient bond and is active.
function hasSufficientBond(
Storage storage $,
address _account,
uint64 _minBond
)
internal
view
returns (bool)
{
IBondManager.Bond storage bond_ = $.bonds[_account];
return bond_.balance >= _minBond && bond_.withdrawalRequestedAt == 0;
}
/// @dev Applies a liveness bond slash with a 50/50 split (payee/burn).
/// @param $ Storage reference.
/// @param _payer Account whose bond is debited.
/// @param _payee Account credited with half of the debited bond.
/// @param _livenessBond Liveness bond amount in gwei.
function settleLivenessBond(
Storage storage $,
address _payer,
address _payee,
uint64 _livenessBond
)
internal
{
// We try to debit the full liveness bond, but since it is best effort
// the amount may be lower.
uint64 debited = _debitBond($, _payer, _livenessBond);
if (debited == 0) return;
uint64 payeeAmount = debited / 2;
uint64 slashedAmount = debited - payeeAmount;
if (payeeAmount > 0) {
_creditBond($, _payee, payeeAmount);
}
emit IBondManager.LivenessBondSettled(
_payer, _payee, _livenessBond, payeeAmount, slashedAmount
);
}
// ---------------------------------------------------------------
// Private Functions
// ---------------------------------------------------------------
/// @dev Debits a bond with best effort.
function _debitBond(
Storage storage $,
address _account,
uint64 _amount
)
private
returns (uint64 debited_)
{
IBondManager.Bond storage bond_ = $.bonds[_account];
if (bond_.balance <= _amount) {
debited_ = bond_.balance;
bond_.balance = 0;
} else {
debited_ = _amount;
bond_.balance = bond_.balance - _amount;
}
}
/// @dev Credits a bond balance.
function _creditBond(Storage storage $, address _account, uint64 _amount) private {
IBondManager.Bond storage bond_ = $.bonds[_account];
bond_.balance = bond_.balance + _amount;
}
/// @dev Converts bond amounts in gwei to token units (18 decimals).
function _toTokenAmount(uint64 _amount) private pure returns (uint256) {
return uint256(_amount) * GWEI_UNIT;
}
// ---------------------------------------------------------------
// Errors
// ---------------------------------------------------------------
error InvalidAddress();
error MustMaintainMinBond();
error NoBondToWithdraw();
error NoWithdrawalRequested();
error WithdrawalAlreadyRequested();
}
contracts/layer1/core/libs/LibTransitionCodec.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IInbox } from "../iface/IInbox.sol";
import { LibPackUnpack as P } from "./LibPackUnpack.sol";
/// @title LibTransitionCodec
/// @notice Shared transition encode/decode helpers to avoid duplication across codecs.
/// @custom:security-contact security@taiko.xyz
library LibTransitionCodec {
uint256 internal constant TRANSITION_SIZE = 58;
function encodeTransition(
uint256 _ptr,
IInbox.Transition memory _transition
)
internal
pure
returns (uint256 newPtr_)
{
newPtr_ = P.packAddress(_ptr, _transition.proposer);
newPtr_ = P.packUint48(newPtr_, _transition.timestamp);
newPtr_ = P.packBytes32(newPtr_, _transition.blockHash);
}
function decodeTransition(uint256 _ptr)
internal
pure
returns (IInbox.Transition memory transition_, uint256 newPtr_)
{
(transition_.proposer, newPtr_) = P.unpackAddress(_ptr);
(transition_.timestamp, newPtr_) = P.unpackUint48(newPtr_);
(transition_.blockHash, newPtr_) = P.unpackBytes32(newPtr_);
}
}
contracts/layer1/core/iface/IInbox.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { LibBlobs } from "../libs/LibBlobs.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 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 ERC20 bond token address
address bondToken;
/// @notice The minimum bond a proposer is required to have in gwei
uint64 minBond;
/// @notice The liveness bond amount in gwei
uint64 livenessBond;
/// @notice The withdrawal delay in seconds
uint48 withdrawalDelay;
/// @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 Proposal
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 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 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 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 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 Proved event
struct ProvedEventPayload {
/// @notice The ID of the first proposal being proven.
uint48 firstProposalId;
/// @notice The ID of the first proposal that had not been proven before.
uint48 firstNewProposalId;
/// @notice The ID of the last proposal being proven.
uint48 lastProposalId;
/// @notice The actual prover who generated the proof.
address actualProver;
/// @notice Whether the checkpoint was synced.
bool checkpointSynced;
}
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
/// @notice Emitted when a new proposal is proposed.
/// @param id Unique identifier for the proposal.
/// @param proposer Address of the proposer.
/// @param parentProposalHash The hash of the parent proposal (zero for genesis).
/// @param endOfSubmissionWindowTimestamp Last slot timestamp where the preconfer can propose.
/// @param basefeeSharingPctg The percentage of base fee paid to coinbase.
/// @param sources Array of derivation sources for this proposal.
event Proposed(
uint48 indexed id,
address indexed proposer,
bytes32 parentProposalHash,
uint48 endOfSubmissionWindowTimestamp,
uint8 basefeeSharingPctg,
DerivationSource[] sources
);
/// @notice Emitted when a proof is submitted
/// @param firstProposalId The first proposal ID covered by the proof (may include finalized ids)
/// @param firstNewProposalId The first proposal ID that was newly proven by this proof
/// @param lastProposalId The last proposal ID covered by the proof
/// @param actualProver The prover that submitted the proof
/// @param checkpointSynced Whether a checkpoint was synced as part of this proof
event Proved(
uint48 firstProposalId,
uint48 firstNewProposalId,
uint48 lastProposalId,
address indexed actualProver,
bool checkpointSynced
);
event DebugHash(uint8 index, bytes32 hash);
event DebugNumber(uint8 index, uint48 number);
event DebugAddress(uint8 index, address addr);
// ---------------------------------------------------------------
// External Transactional Functions
// ---------------------------------------------------------------
/// @notice Proposes new L2 blocks and forced inclusions to the rollup using blobs for DA.
/// @param _lookahead Encoded data forwarded to the proposer checker (i.e. lookahead payloads).
/// @param _data The encoded ProposeInput struct.
function propose(bytes calldata _lookahead, bytes calldata _data) external;
/// @notice Verifies a batch proof covering multiple consecutive proposals and finalizes them.
/// @param _data The encoded ProveInput struct.
/// @param _proof The validity proof for the batch of proposals.
function prove(bytes calldata _data, bytes calldata _proof) external;
// ---------------------------------------------------------------
// External View Functions
// ---------------------------------------------------------------
/// @notice Returns the configuration parameters of the Inbox contract
/// @return config_ The configuration struct containing all immutable parameters
function getConfig() external view returns (Config memory config_);
/// @notice Returns the current core state.
/// @return The core state struct.
function getCoreState() external view returns (CoreState memory);
/// @notice Returns the proposal hash for a given proposal ID.
/// @param _proposalId The proposal ID to look up.
/// @return proposalHash_ The hash stored at the proposal's ring buffer slot.
function getProposalHash(uint256 _proposalId) external view returns (bytes32 proposalHash_);
}
node_modules/solady/src/utils/EfficientHashLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Library for efficiently performing keccak256 hashes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EfficientHashLib.sol)
/// @dev To avoid stack-too-deep, you can use:
/// ```
/// bytes32[] memory buffer = EfficientHashLib.malloc(10);
/// EfficientHashLib.set(buffer, 0, value0);
/// ..
/// EfficientHashLib.set(buffer, 9, value9);
/// bytes32 finalHash = EfficientHashLib.hash(buffer);
/// ```
library EfficientHashLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MALLOC-LESS HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `keccak256(abi.encode(v0))`.
function hash(bytes32 v0) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
result := keccak256(0x00, 0x20)
}
}
/// @dev Returns `keccak256(abi.encode(v0))`.
function hash(uint256 v0) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
result := keccak256(0x00, 0x20)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1))`.
function hash(bytes32 v0, bytes32 v1) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
mstore(0x20, v1)
result := keccak256(0x00, 0x40)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1))`.
function hash(uint256 v0, uint256 v1) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, v0)
mstore(0x20, v1)
result := keccak256(0x00, 0x40)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
result := keccak256(m, 0x60)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
function hash(uint256 v0, uint256 v1, uint256 v2) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
result := keccak256(m, 0x60)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
result := keccak256(m, 0x80)
}
}
/// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
result := keccak256(m, 0x80)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
result := keccak256(m, 0xa0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
result := keccak256(m, 0xa0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4, bytes32 v5)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
result := keccak256(m, 0xc0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4, uint256 v5)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
result := keccak256(m, 0xc0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
result := keccak256(m, 0xe0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
result := keccak256(m, 0xe0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
result := keccak256(m, 0x100)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
result := keccak256(m, 0x100)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
result := keccak256(m, 0x120)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
result := keccak256(m, 0x120)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
result := keccak256(m, 0x140)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
result := keccak256(m, 0x140)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
result := keccak256(m, 0x160)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
result := keccak256(m, 0x160)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10,
bytes32 v11
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
result := keccak256(m, 0x180)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10,
uint256 v11
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
result := keccak256(m, 0x180)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10,
bytes32 v11,
bytes32 v12
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
result := keccak256(m, 0x1a0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10,
uint256 v11,
uint256 v12
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
result := keccak256(m, 0x1a0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
function hash(
bytes32 v0,
bytes32 v1,
bytes32 v2,
bytes32 v3,
bytes32 v4,
bytes32 v5,
bytes32 v6,
bytes32 v7,
bytes32 v8,
bytes32 v9,
bytes32 v10,
bytes32 v11,
bytes32 v12,
bytes32 v13
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
mstore(add(m, 0x1a0), v13)
result := keccak256(m, 0x1c0)
}
}
/// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
function hash(
uint256 v0,
uint256 v1,
uint256 v2,
uint256 v3,
uint256 v4,
uint256 v5,
uint256 v6,
uint256 v7,
uint256 v8,
uint256 v9,
uint256 v10,
uint256 v11,
uint256 v12,
uint256 v13
) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
mstore(m, v0)
mstore(add(m, 0x20), v1)
mstore(add(m, 0x40), v2)
mstore(add(m, 0x60), v3)
mstore(add(m, 0x80), v4)
mstore(add(m, 0xa0), v5)
mstore(add(m, 0xc0), v6)
mstore(add(m, 0xe0), v7)
mstore(add(m, 0x100), v8)
mstore(add(m, 0x120), v9)
mstore(add(m, 0x140), v10)
mstore(add(m, 0x160), v11)
mstore(add(m, 0x180), v12)
mstore(add(m, 0x1a0), v13)
result := keccak256(m, 0x1c0)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTES32 BUFFER HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `keccak256(abi.encode(buffer[0], .., buffer[buffer.length - 1]))`.
function hash(bytes32[] memory buffer) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := keccak256(add(buffer, 0x20), shl(5, mload(buffer)))
}
}
/// @dev Sets `buffer[i]` to `value`, without a bounds check.
/// Returns the `buffer` for function chaining.
function set(bytes32[] memory buffer, uint256 i, bytes32 value)
internal
pure
returns (bytes32[] memory)
{
/// @solidity memory-safe-assembly
assembly {
mstore(add(buffer, shl(5, add(1, i))), value)
}
return buffer;
}
/// @dev Sets `buffer[i]` to `value`, without a bounds check.
/// Returns the `buffer` for function chaining.
function set(bytes32[] memory buffer, uint256 i, uint256 value)
internal
pure
returns (bytes32[] memory)
{
/// @solidity memory-safe-assembly
assembly {
mstore(add(buffer, shl(5, add(1, i))), value)
}
return buffer;
}
/// @dev Returns `new bytes32[](n)`, without zeroing out the memory.
function malloc(uint256 n) internal pure returns (bytes32[] memory buffer) {
/// @solidity memory-safe-assembly
assembly {
buffer := mload(0x40)
mstore(buffer, n)
mstore(0x40, add(shl(5, add(1, n)), buffer))
}
}
/// @dev Frees memory that has been allocated for `buffer`.
/// No-op if `buffer.length` is zero, or if new memory has been allocated after `buffer`.
function free(bytes32[] memory buffer) internal pure {
/// @solidity memory-safe-assembly
assembly {
let n := mload(buffer)
mstore(shl(6, lt(iszero(n), eq(add(shl(5, add(1, n)), buffer), mload(0x40)))), buffer)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EQUALITY CHECKS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `a == abi.decode(b, (bytes32))`.
function eq(bytes32 a, bytes memory b) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := and(eq(0x20, mload(b)), eq(a, mload(add(b, 0x20))))
}
}
/// @dev Returns `abi.decode(a, (bytes32)) == a`.
function eq(bytes memory a, bytes32 b) internal pure returns (bool result) {
/// @solidity memory-safe-assembly
assembly {
result := and(eq(0x20, mload(a)), eq(b, mload(add(a, 0x20))))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTE SLICE HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function hash(bytes memory b, uint256 start, uint256 end)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
end := xor(end, mul(xor(end, n), lt(n, end)))
start := xor(start, mul(xor(start, n), lt(n, start)))
result := keccak256(add(add(b, 0x20), start), mul(gt(end, start), sub(end, start)))
}
}
/// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
function hash(bytes memory b, uint256 start) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
start := xor(start, mul(xor(start, n), lt(n, start)))
result := keccak256(add(add(b, 0x20), start), mul(gt(n, start), sub(n, start)))
}
}
/// @dev Returns the keccak256 of the bytes.
function hash(bytes memory b) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := keccak256(add(b, 0x20), mload(b))
}
}
/// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function hashCalldata(bytes calldata b, uint256 start, uint256 end)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(end, start), sub(end, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := keccak256(mload(0x40), n)
}
}
/// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
function hashCalldata(bytes calldata b, uint256 start) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(b.length, start), sub(b.length, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := keccak256(mload(0x40), n)
}
}
/// @dev Returns the keccak256 of the bytes.
function hashCalldata(bytes calldata b) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
calldatacopy(mload(0x40), b.offset, b.length)
result := keccak256(mload(0x40), b.length)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SHA2-256 HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `sha256(abi.encode(b))`. Yes, it's more efficient.
function sha2(bytes32 b) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, b)
result := mload(staticcall(gas(), 2, 0x00, 0x20, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function sha2(bytes memory b, uint256 start, uint256 end)
internal
view
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
end := xor(end, mul(xor(end, n), lt(n, end)))
start := xor(start, mul(xor(start, n), lt(n, start)))
// forgefmt: disable-next-item
result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
mul(gt(end, start), sub(end, start)), 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
function sha2(bytes memory b, uint256 start) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let n := mload(b)
start := xor(start, mul(xor(start, n), lt(n, start)))
// forgefmt: disable-next-item
result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
mul(gt(n, start), sub(n, start)), 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the bytes.
function sha2(bytes memory b) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(staticcall(gas(), 2, add(b, 0x20), mload(b), 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
/// `start` and `end` are byte offsets.
function sha2Calldata(bytes calldata b, uint256 start, uint256 end)
internal
view
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(end, start), sub(end, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
function sha2Calldata(bytes calldata b, uint256 start) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
let n := mul(gt(b.length, start), sub(b.length, start))
calldatacopy(mload(0x40), add(b.offset, start), n)
result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
/// @dev Returns the sha256 of the bytes.
function sha2Calldata(bytes calldata b) internal view returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
calldatacopy(mload(0x40), b.offset, b.length)
result := mload(staticcall(gas(), 2, mload(0x40), b.length, 0x01, 0x20))
if iszero(returndatasize()) { invalid() }
}
}
}
contracts/layer1/core/impl/Inbox.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { IBondManager } from "../iface/IBondManager.sol";
import { ICodec } from "../iface/ICodec.sol";
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 { LibBonds } from "../libs/LibBonds.sol";
import { LibCodec } from "../libs/LibCodec.sol";
import { LibForcedInclusion } from "../libs/LibForcedInclusion.sol";
import { LibHashOptimized } from "../libs/LibHashOptimized.sol";
import { LibInboxSetup } from "../libs/LibInboxSetup.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.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 { 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 accounting and liveness bond processing
/// - Finalization of proven proposals with checkpoint rate limiting
/// @custom:security-contact security@taiko.xyz
contract Inbox is IInbox, ICodec, IForcedInclusionStore, IBondManager, EssentialContract {
using LibAddress for address;
using LibBonds for LibBonds.Storage;
using LibForcedInclusion for LibForcedInclusion.Storage;
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 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.
ISignalService internal immutable _signalService;
/// @notice ERC20 token used as bond.
IERC20 internal immutable _bondToken;
/// @notice Minimum bond the proposer is required to have in gwei.
uint64 internal immutable _minBond;
/// @notice Liveness bond amount in gwei.
uint64 internal immutable _livenessBond;
/// @notice Time delay required before withdrawal after request.
uint48 internal immutable _withdrawalDelay;
/// @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;
/// @dev Storage for bond balances.
LibBonds.Storage private _bondStorage;
uint256[43] private __gap;
// ---------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------
/// @notice Initializes the Inbox contract
/// @param _config Configuration struct containing all constructor parameters
constructor(Config memory _config) {
LibInboxSetup.validateConfig(_config);
_proofVerifier = IProofVerifier(_config.proofVerifier);
_proposerChecker = IProposerChecker(_config.proposerChecker);
_proverWhitelist = IProverWhitelist(_config.proverWhitelist);
_signalService = ISignalService(_config.signalService);
_bondToken = IERC20(_config.bondToken);
_minBond = _config.minBond;
_livenessBond = _config.livenessBond;
_withdrawalDelay = _config.withdrawalDelay;
_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,
Proposal memory proposal,
bytes32 genesisProposalHash
) = LibInboxSetup.activate(_lastPacayaBlockHash, activationTimestamp);
activationTimestamp = newActivationTimestamp;
_coreState = state;
_setProposalHash(0, genesisProposalHash);
_emitProposedEvent(proposal);
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 = LibCodec.decodeProposeInput(_data);
_validateProposeInput(input);
uint48 nextProposalId = _coreState.nextProposalId;
uint48 lastProposalBlockId = _coreState.lastProposalBlockId;
uint48 lastFinalizedProposalId = _coreState.lastFinalizedProposalId;
require(nextProposalId > 0, ActivationRequired());
Proposal memory proposal = _buildProposal(
input, _lookahead, nextProposalId, lastProposalBlockId, lastFinalizedProposalId
);
_coreState.nextProposalId = nextProposalId + 1;
_coreState.lastProposalBlockId = uint48(block.number);
_setProposalHash(proposal.id, LibHashOptimized.hashProposal(proposal));
_emitProposedEvent(proposal);
}
}
/// @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 = LibCodec.decodeProveInput(_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) {
_processLivenessBond(commitment, offset);
}
// -----------------------------------------------------------------------------
// 4. Sync checkpoint
// -----------------------------------------------------------------------------
bool checkpointSynced = input.forceCheckpointSync
|| block.timestamp >= state.lastCheckpointTimestamp + _minCheckpointDelay;
if (checkpointSynced) {
_signalService.saveCheckpoint(
ICheckpointStore.Checkpoint({
blockNumber: commitment.endBlockNumber,
stateRoot: commitment.endStateRoot,
blockHash: commitment.transitions[numProposals - 1].blockHash
})
);
state.lastCheckpointTimestamp = uint48(block.timestamp);
}
// ---------------------------------------------------------
// 5. Compute proposalAge (for single-proposal proofs only)
// ---------------------------------------------------------
uint256 proposalAge;
if (numProposals == 1) {
// We count proposalAge as the time since it became available for proving.
proposalAge = block.timestamp
- commitment.transitions[offset].timestamp.max(state.lastFinalizedTimestamp);
}
// ---------------------------------------------------------
// 6. 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(
commitment.firstProposalId,
commitment.firstProposalId + offset,
uint48(lastProposalId),
commitment.actualProver,
checkpointSynced
);
// ---------------------------------------------------------
// 7. Verify the proof
// ---------------------------------------------------------
bytes32 commitmentHash = LibHashOptimized.hashCommitment(commitment);
emit DebugHash(1, commitmentHash);
emit DebugNumber(2, commitment.firstProposalId);
emit DebugHash(3, commitment.firstProposalParentBlockHash);
emit DebugHash(4, commitment.lastProposalHash);
emit DebugAddress(5, commitment.actualProver);
emit DebugNumber(6, commitment.endBlockNumber);
emit DebugHash(7, commitment.endStateRoot);
emit DebugHash(8, commitment.transitions[0].blockHash);
emit DebugAddress(9, commitment.transitions[0].proposer);
emit DebugNumber(11, commitment.transitions[0].timestamp);
_proofVerifier.verifyProof(
proposalAge, commitmentHash, _proof
);
}
}
/// @inheritdoc IBondManager
function deposit(uint64 _amount) external nonReentrant {
_bondStorage.deposit(_bondToken, msg.sender, msg.sender, _amount, true);
}
/// @inheritdoc IBondManager
function depositTo(address _recipient, uint64 _amount) external nonReentrant {
_bondStorage.deposit(_bondToken, msg.sender, _recipient, _amount, false);
}
/// @inheritdoc IBondManager
function withdraw(address _to, uint64 _amount) external nonReentrant {
_bondStorage.withdraw(_bondToken, msg.sender, _to, _amount, _minBond, _withdrawalDelay);
}
/// @inheritdoc IBondManager
function requestWithdrawal() external nonReentrant {
_bondStorage.requestWithdrawal(msg.sender, _withdrawalDelay);
}
/// @inheritdoc IBondManager
function cancelWithdrawal() external nonReentrant {
_bondStorage.cancelWithdrawal(msg.sender);
}
/// @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 = _forcedInclusionStorage.saveForcedInclusion(
_forcedInclusionFeeInGwei, _forcedInclusionFeeDoubleThreshold, _blobReference
);
// Refund excess payment to the sender
if (refund > 0) {
msg.sender.sendEtherAndVerify(refund);
}
}
/// @inheritdoc ICodec
function encodeProposeInput(IInbox.ProposeInput calldata _input)
external
pure
returns (bytes memory encoded_)
{
return LibCodec.encodeProposeInput(_input);
}
/// @inheritdoc ICodec
function decodeProposeInput(bytes calldata _data)
external
pure
returns (IInbox.ProposeInput memory input_)
{
return LibCodec.decodeProposeInput(_data);
}
/// @inheritdoc ICodec
function encodeProveInput(IInbox.ProveInput calldata _input)
external
pure
returns (bytes memory encoded_)
{
return LibCodec.encodeProveInput(_input);
}
/// @inheritdoc ICodec
function decodeProveInput(bytes calldata _data)
external
pure
returns (IInbox.ProveInput memory input_)
{
return LibCodec.decodeProveInput(_data);
}
/// @inheritdoc ICodec
function hashProposal(IInbox.Proposal calldata _proposal) external pure returns (bytes32) {
return LibHashOptimized.hashProposal(_proposal);
}
/// @inheritdoc ICodec
function hashCommitment(IInbox.Commitment calldata _commitment)
external
pure
returns (bytes32)
{
return LibHashOptimized.hashCommitment(_commitment);
}
// ---------------------------------------------------------------
// External and Public View Functions
// ---------------------------------------------------------------
/// @inheritdoc IBondManager
function getBond(address _address) external view returns (Bond memory bond_) {
return _bondStorage.getBond(_address);
}
/// @inheritdoc IForcedInclusionStore
function getCurrentForcedInclusionFee() external view returns (uint64 feeInGwei_) {
return _forcedInclusionStorage.getCurrentForcedInclusionFee(
_forcedInclusionFeeInGwei, _forcedInclusionFeeDoubleThreshold
);
}
/// @inheritdoc IForcedInclusionStore
function getForcedInclusions(
uint48 _start,
uint48 _maxCount
)
external
view
returns (IForcedInclusionStore.ForcedInclusion[] memory inclusions_)
{
return _forcedInclusionStorage.getForcedInclusions(_start, _maxCount);
}
/// @inheritdoc IForcedInclusionStore
function getForcedInclusionState() external view returns (uint48 head_, uint48 tail_) {
return _forcedInclusionStorage.getForcedInclusionState();
}
/// @inheritdoc IInbox
function getConfig() external view returns (Config memory config_) {
config_ = Config({
proofVerifier: address(_proofVerifier),
proposerChecker: address(_proposerChecker),
proverWhitelist: address(_proverWhitelist),
signalService: address(_signalService),
bondToken: address(_bondToken),
minBond: _minBond,
livenessBond: _livenessBond,
withdrawalDelay: _withdrawalDelay,
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.
/// This function also checks:
/// - If `msg.sender` can propose.
/// - If `msg.sender` has sufficient bond.
/// @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 set.
function _buildProposal(
ProposeInput memory _input,
bytes calldata _lookahead,
uint48 _nextProposalId,
uint48 _lastProposalBlockId,
uint48 _lastFinalizedProposalId
)
private
returns (Proposal memory proposal_)
{
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
// set endOfSubmissionWindowTimestamp = 0, and do not require a bond
// Otherwise, only the current preconfer can propose
uint48 endOfSubmissionWindowTimestamp;
if (!result.allowsPermissionless) {
endOfSubmissionWindowTimestamp =
_proposerChecker.checkProposer(msg.sender, _lookahead);
require(_bondStorage.hasSufficientBond(msg.sender, _minBond), InsufficientBond());
}
// Use previous block as the origin for the proposal to be able to call `blockhash`
uint256 parentBlockNumber = block.number - 1;
proposal_ = Proposal({
id: _nextProposalId,
timestamp: uint48(block.timestamp),
endOfSubmissionWindowTimestamp: endOfSubmissionWindowTimestamp,
proposer: msg.sender,
parentProposalHash: getProposalHash(_nextProposalId - 1),
originBlockNumber: uint48(parentBlockNumber),
originBlockHash: blockhash(parentBlockNumber),
basefeeSharingPctg: _basefeeSharingPctg,
sources: result.sources
});
}
}
/// @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 =
$.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
_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 processes liveness bond settlement if applicable.
/// @dev Settlement rules:
/// - On-time (within provingWindow + sequential grace): No bond changes.
/// - Late: Liveness bond slash with 50% credited to the actual prover and 50% burned.
/// @param _commitment The commitment data.
/// @param _offset The offset to the first unfinalized proposal.
function _processLivenessBond(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;
}
_bondStorage.settleLivenessBond(
_commitment.transitions[_offset].proposer, _commitment.actualProver, _livenessBond
);
}
}
/// @dev Emits the Proposed event
function _emitProposedEvent(Proposal memory _proposal) private {
emit Proposed(
_proposal.id,
_proposal.proposer,
_proposal.parentProposalHash,
_proposal.endOfSubmissionWindowTimestamp,
_proposal.basefeeSharingPctg,
_proposal.sources
);
}
// ---------------------------------------------------------------
// 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 InsufficientBond();
error LastProposalAlreadyFinalized();
error LastProposalHashMismatch();
error LastProposalIdTooLarge();
error NotEnoughCapacity();
error ParentBlockHashMismatch();
error ProverNotWhitelisted();
error UnprocessedForcedInclusionIsDue();
}
node_modules/@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}
node_modules/@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.0;
import "./OwnableUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function __Ownable2Step_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable2Step_init_unchained() internal onlyInitializing {
}
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
contracts/layer1/core/libs/LibCodec.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IInbox } from "../iface/IInbox.sol";
import { LibPackUnpack as P } from "./LibPackUnpack.sol";
import { LibTransitionCodec } from "./LibTransitionCodec.sol";
/// @title LibCodec
/// @notice Compact encoder/decoder for Inbox inputs using LibPackUnpack.
/// @custom:security-contact security@taiko.xyz
library LibCodec {
// ---------------------------------------------------------------
// ProposeInputCodec Functions
// ---------------------------------------------------------------
/// @dev Encodes propose input data using compact packing.
function encodeProposeInput(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);
}
/// @dev Decodes propose input data using compact packing.
function decodeProposeInput(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,) = P.unpackUint8(ptr);
}
// ---------------------------------------------------------------
// ProveInputCodec Functions
// ---------------------------------------------------------------
/// @dev Encodes prove input data using compact packing.
function encodeProveInput(IInbox.ProveInput memory _input)
internal
pure
returns (bytes memory encoded_)
{
IInbox.Commitment memory c = _input.commitment;
uint256 bufferSize = _calculateProveInputSize(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) {
ptr = LibTransitionCodec.encodeTransition(ptr, c.transitions[i]);
}
// Encode forceCheckpointSync
P.packUint8(ptr, _input.forceCheckpointSync ? 1 : 0);
}
/// @dev Decodes prove input data using compact packing.
function decodeProveInput(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) = LibTransitionCodec.decodeTransition(ptr);
}
// Decode forceCheckpointSync
uint8 forceCheckpointSyncByte;
(forceCheckpointSyncByte,) = P.unpackUint8(ptr);
input_.forceCheckpointSync = forceCheckpointSyncByte != 0;
}
// ---------------------------------------------------------------
// Private Functions
// ---------------------------------------------------------------
/// @dev Calculates the size needed for ProveInput encoding.
/// @param _numTransitions Number of transitions in the array.
/// @return size_ Total byte size needed.
function _calculateProveInputSize(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
size_ = 131 + (_numTransitions * LibTransitionCodec.TRANSITION_SIZE);
}
}
}
contracts/layer1/core/iface/ICodec.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { IInbox } from "./IInbox.sol";
/// @title ICodec
/// @notice Interface for Inbox encoder/decoder and hashing functions
/// @dev Input validation assumptions:
/// - All decode functions may revert on malformed input data
/// - Array inputs should be bounded to prevent excessive gas usage
/// - Struct fields are not validated for business logic constraints
/// - Hash functions assume well-formed input structures
/// @dev Compatibility warning:
/// - Different codec implementations produce INCOMPATIBLE encoded outputs and hashes for the same
/// inputs
/// - Codec implementations cannot be used interchangeably
/// - System upgrades between codec types require careful migration planning
/// @custom:security-contact security@taiko.xyz
interface ICodec {
// ---------------------------------------------------------------
// ProposeInputCodec Functions
// ---------------------------------------------------------------
/// @notice Encodes propose input data
/// @param _input The ProposeInput to encode
/// @return encoded_ The encoded data
function encodeProposeInput(IInbox.ProposeInput calldata _input)
external
pure
returns (bytes memory encoded_);
/// @notice Decodes propose data
/// @param _data The encoded data
/// @return input_ The decoded ProposeInput
/// @dev Reverts on malformed or truncated input data
function decodeProposeInput(bytes calldata _data)
external
pure
returns (IInbox.ProposeInput memory input_);
// ---------------------------------------------------------------
// ProveInputCodec Functions
// ---------------------------------------------------------------
/// @notice Encodes prove input data
/// @param _input The ProveInput to encode
/// @return encoded_ The encoded data
function encodeProveInput(IInbox.ProveInput calldata _input)
external
pure
returns (bytes memory encoded_);
/// @notice Decodes prove input data
/// @param _data The encoded data
/// @return input_ The decoded ProveInput
/// @dev Reverts on malformed or truncated input data
function decodeProveInput(bytes calldata _data)
external
pure
returns (IInbox.ProveInput memory input_);
// ---------------------------------------------------------------
// Hashing Functions
// ---------------------------------------------------------------
/// @notice Hashing for Proposal structs
/// @param _proposal The proposal to hash
/// @return The hash of the proposal
function hashProposal(IInbox.Proposal calldata _proposal) external pure returns (bytes32);
/// @notice Hashing for commitment data
/// @param _commitment The commitment data to hash
/// @return The hash of the commitment
function hashCommitment(IInbox.Commitment calldata _commitment) external pure returns (bytes32);
}
node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
node_modules/@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}
contracts/shared/signal/ICheckpointStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title ICheckpointStore
/// @notice Interface for storing and retrieving checkpoints
/// @custom:security-contact security@taiko.xyz
interface ICheckpointStore {
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @notice Represents a synced checkpoint
struct Checkpoint {
/// @notice The block number associated with the checkpoint.
uint48 blockNumber;
/// @notice The block hash for the end (last) L2 block in this proposal.
bytes32 blockHash;
/// @notice The state root for the end (last) L2 block in this proposal.
bytes32 stateRoot;
}
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
/// @notice Emitted when a checkpoint is saved
/// @param blockNumber The block number
/// @param blockHash The block hash
/// @param stateRoot The state root
event CheckpointSaved(uint48 indexed blockNumber, bytes32 blockHash, bytes32 stateRoot);
// ---------------------------------------------------------------
// External Functions
// ---------------------------------------------------------------
/// @notice Saves a checkpoint
/// @param _checkpoint The checkpoint data to persist
function saveCheckpoint(Checkpoint calldata _checkpoint) external;
/// @notice Gets a checkpoint by its block number
/// @param _blockNumber The block number associated with the checkpoint
/// @return _ The checkpoint
function getCheckpoint(uint48 _blockNumber) external view returns (Checkpoint memory);
}
node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
contracts/layer1/core/libs/LibPackUnpack.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/// @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/shared/libs/LibAddress.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
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.26;
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.26;
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.26;
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 Minimum ring buffer size to keep one slot reserved in capacity calculations.
uint256 public constant MIN_RING_BUFFER_SIZE = 2;
/// @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.proofVerifier != address(0), ProofVerifierZero());
require(_config.proposerChecker != address(0), ProposerCheckerZero());
require(_config.signalService != address(0), SignalServiceZero());
require(_config.bondToken != address(0), BondTokenZero());
require(_config.provingWindow != 0, ProvingWindowZero());
require(_config.ringBufferSize >= MIN_RING_BUFFER_SIZE, 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 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.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;
genesisProposalHash_ = LibHashOptimized.hashProposal(proposal_);
}
// ---------------------------------------------------------------
// Errors
// ---------------------------------------------------------------
error ActivationPeriodExpired();
error BasefeeSharingPctgTooLarge();
error BondTokenZero();
error ForcedInclusionFeeDoubleThresholdZero();
error ForcedInclusionFeeInGweiZero();
error InvalidLastPacayaBlockHash();
error MinForcedInclusionCountZero();
error PermissionlessInclusionMultiplierTooSmall();
error ProofVerifierZero();
error ProposerCheckerZero();
error ProvingWindowZero();
error RingBufferSizeTooSmall();
error SignalServiceZero();
}
Compiler Settings
{"viaIR":true,"remappings":["openzeppelin/=node_modules/@openzeppelin/","@openzeppelin/=node_modules/@openzeppelin/","@openzeppelin-upgrades/contracts/=node_modules/@openzeppelin/contracts-upgradeable/","@risc0/contracts/=node_modules/risc0-ethereum/contracts/src/","@solady/=node_modules/solady/","solady/src/=node_modules/solady/src/","solady/utils/=node_modules/solady/src/utils/","@optimism/=node_modules/optimism/","@sp1-contracts/=node_modules/sp1-contracts/contracts/","forge-std/=node_modules/forge-std/","@p256-verifier/contracts/=node_modules/p256-verifier/src/","@eth-fabric/urc/=node_modules/urc/src/","ds-test/=node_modules/ds-test/","src/=contracts/","test/=test/","script/=script/","optimism/=node_modules/optimism/","p256-verifier/=node_modules/p256-verifier/","risc0-ethereum/=node_modules/risc0-ethereum/","sp1-contracts/=node_modules/sp1-contracts/","urc/=node_modules/urc/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{"contracts/layer1/core/libs/LibInboxSetup.sol":{"LibInboxSetup":"0xb2c8E57eb1eb0b686B63f58E53f859bEA615677B"},"contracts/layer1/core/libs/LibForcedInclusion.sol":{"LibForcedInclusion":"0x8bBdF7B3D44c1CF6aA64Db449E93aD5C0d10E63c"}},"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":"_bondToken","internalType":"address"},{"type":"uint64","name":"_minBond","internalType":"uint64"},{"type":"uint64","name":"_livenessBond","internalType":"uint64"},{"type":"uint48","name":"_withdrawalDelay","internalType":"uint48"}]},{"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":"InsufficientBond","inputs":[]},{"type":"error","name":"InvalidAddress","inputs":[]},{"type":"error","name":"LastProposalAlreadyFinalized","inputs":[]},{"type":"error","name":"LastProposalHashMismatch","inputs":[]},{"type":"error","name":"LastProposalIdTooLarge","inputs":[]},{"type":"error","name":"LengthExceedsUint16","inputs":[]},{"type":"error","name":"MustMaintainMinBond","inputs":[]},{"type":"error","name":"NoBlobs","inputs":[]},{"type":"error","name":"NoBondToWithdraw","inputs":[]},{"type":"error","name":"NoWithdrawalRequested","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":"WithdrawalAlreadyRequested","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":"BondDeposited","inputs":[{"type":"address","name":"depositor","internalType":"address","indexed":true},{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint64","name":"amount","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"BondWithdrawn","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint64","name":"amount","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"DebugAddress","inputs":[{"type":"uint8","name":"index","internalType":"uint8","indexed":false},{"type":"address","name":"addr","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"DebugHash","inputs":[{"type":"uint8","name":"index","internalType":"uint8","indexed":false},{"type":"bytes32","name":"hash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"DebugNumber","inputs":[{"type":"uint8","name":"index","internalType":"uint8","indexed":false},{"type":"uint48","name":"number","internalType":"uint48","indexed":false}],"anonymous":false},{"type":"event","name":"ForcedInclusionSaved","inputs":[{"type":"tuple","name":"forcedInclusion","internalType":"struct IForcedInclusionStore.ForcedInclusion","indexed":false,"components":[{"type":"uint64","name":"feeInGwei","internalType":"uint64"},{"type":"tuple","name":"blobSlice","internalType":"struct LibBlobs.BlobSlice","components":[{"type":"bytes32[]","name":"blobHashes","internalType":"bytes32[]"},{"type":"uint24","name":"offset","internalType":"uint24"},{"type":"uint48","name":"timestamp","internalType":"uint48"}]}]}],"anonymous":false},{"type":"event","name":"InboxActivated","inputs":[{"type":"bytes32","name":"lastPacayaBlockHash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"LivenessBondSettled","inputs":[{"type":"address","name":"payer","internalType":"address","indexed":true},{"type":"address","name":"payee","internalType":"address","indexed":true},{"type":"uint64","name":"livenessBond","internalType":"uint64","indexed":false},{"type":"uint64","name":"credited","internalType":"uint64","indexed":false},{"type":"uint64","name":"slashed","internalType":"uint64","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":"uint48","name":"id","internalType":"uint48","indexed":true},{"type":"address","name":"proposer","internalType":"address","indexed":true},{"type":"bytes32","name":"parentProposalHash","internalType":"bytes32","indexed":false},{"type":"uint48","name":"endOfSubmissionWindowTimestamp","internalType":"uint48","indexed":false},{"type":"uint8","name":"basefeeSharingPctg","internalType":"uint8","indexed":false},{"type":"tuple[]","name":"sources","internalType":"struct IInbox.DerivationSource[]","indexed":false,"components":[{"type":"bool","name":"isForcedInclusion","internalType":"bool"},{"type":"tuple","name":"blobSlice","internalType":"struct LibBlobs.BlobSlice","components":[{"type":"bytes32[]","name":"blobHashes","internalType":"bytes32[]"},{"type":"uint24","name":"offset","internalType":"uint24"},{"type":"uint48","name":"timestamp","internalType":"uint48"}]}]}],"anonymous":false},{"type":"event","name":"Proved","inputs":[{"type":"uint48","name":"firstProposalId","internalType":"uint48","indexed":false},{"type":"uint48","name":"firstNewProposalId","internalType":"uint48","indexed":false},{"type":"uint48","name":"lastProposalId","internalType":"uint48","indexed":false},{"type":"address","name":"actualProver","internalType":"address","indexed":true},{"type":"bool","name":"checkpointSynced","internalType":"bool","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":"event","name":"WithdrawalCancelled","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"WithdrawalRequested","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint48","name":"withdrawableAt","internalType":"uint48","indexed":false}],"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":"nonpayable","outputs":[],"name":"cancelWithdrawal","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"input_","internalType":"struct IInbox.ProposeInput","components":[{"type":"uint48","name":"deadline","internalType":"uint48"},{"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":"uint8","name":"numForcedInclusions","internalType":"uint8"}]}],"name":"decodeProposeInput","inputs":[{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"tuple","name":"input_","internalType":"struct IInbox.ProveInput","components":[{"type":"tuple","name":"commitment","internalType":"struct IInbox.Commitment","components":[{"type":"uint48","name":"firstProposalId","internalType":"uint48"},{"type":"bytes32","name":"firstProposalParentBlockHash","internalType":"bytes32"},{"type":"bytes32","name":"lastProposalHash","internalType":"bytes32"},{"type":"address","name":"actualProver","internalType":"address"},{"type":"uint48","name":"endBlockNumber","internalType":"uint48"},{"type":"bytes32","name":"endStateRoot","internalType":"bytes32"},{"type":"tuple[]","name":"transitions","internalType":"struct IInbox.Transition[]","components":[{"type":"address","name":"proposer","internalType":"address"},{"type":"uint48","name":"timestamp","internalType":"uint48"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]}]},{"type":"bool","name":"forceCheckpointSync","internalType":"bool"}]}],"name":"decodeProveInput","inputs":[{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deposit","inputs":[{"type":"uint64","name":"_amount","internalType":"uint64"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"depositTo","inputs":[{"type":"address","name":"_recipient","internalType":"address"},{"type":"uint64","name":"_amount","internalType":"uint64"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes","name":"encoded_","internalType":"bytes"}],"name":"encodeProposeInput","inputs":[{"type":"tuple","name":"_input","internalType":"struct IInbox.ProposeInput","components":[{"type":"uint48","name":"deadline","internalType":"uint48"},{"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":"uint8","name":"numForcedInclusions","internalType":"uint8"}]}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes","name":"encoded_","internalType":"bytes"}],"name":"encodeProveInput","inputs":[{"type":"tuple","name":"_input","internalType":"struct IInbox.ProveInput","components":[{"type":"tuple","name":"commitment","internalType":"struct IInbox.Commitment","components":[{"type":"uint48","name":"firstProposalId","internalType":"uint48"},{"type":"bytes32","name":"firstProposalParentBlockHash","internalType":"bytes32"},{"type":"bytes32","name":"lastProposalHash","internalType":"bytes32"},{"type":"address","name":"actualProver","internalType":"address"},{"type":"uint48","name":"endBlockNumber","internalType":"uint48"},{"type":"bytes32","name":"endStateRoot","internalType":"bytes32"},{"type":"tuple[]","name":"transitions","internalType":"struct IInbox.Transition[]","components":[{"type":"address","name":"proposer","internalType":"address"},{"type":"uint48","name":"timestamp","internalType":"uint48"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]}]},{"type":"bool","name":"forceCheckpointSync","internalType":"bool"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"bond_","internalType":"struct IBondManager.Bond","components":[{"type":"uint64","name":"balance","internalType":"uint64"},{"type":"uint48","name":"withdrawalRequestedAt","internalType":"uint48"}]}],"name":"getBond","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"config_","internalType":"struct IInbox.Config","components":[{"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":"bondToken","internalType":"address"},{"type":"uint64","name":"minBond","internalType":"uint64"},{"type":"uint64","name":"livenessBond","internalType":"uint64"},{"type":"uint48","name":"withdrawalDelay","internalType":"uint48"},{"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":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"hashCommitment","inputs":[{"type":"tuple","name":"_commitment","internalType":"struct IInbox.Commitment","components":[{"type":"uint48","name":"firstProposalId","internalType":"uint48"},{"type":"bytes32","name":"firstProposalParentBlockHash","internalType":"bytes32"},{"type":"bytes32","name":"lastProposalHash","internalType":"bytes32"},{"type":"address","name":"actualProver","internalType":"address"},{"type":"uint48","name":"endBlockNumber","internalType":"uint48"},{"type":"bytes32","name":"endStateRoot","internalType":"bytes32"},{"type":"tuple[]","name":"transitions","internalType":"struct IInbox.Transition[]","components":[{"type":"address","name":"proposer","internalType":"address"},{"type":"uint48","name":"timestamp","internalType":"uint48"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]}]}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"hashProposal","inputs":[{"type":"tuple","name":"_proposal","internalType":"struct IInbox.Proposal","components":[{"type":"uint48","name":"id","internalType":"uint48"},{"type":"uint48","name":"timestamp","internalType":"uint48"},{"type":"uint48","name":"endOfSubmissionWindowTimestamp","internalType":"uint48"},{"type":"address","name":"proposer","internalType":"address"},{"type":"bytes32","name":"parentProposalHash","internalType":"bytes32"},{"type":"uint48","name":"originBlockNumber","internalType":"uint48"},{"type":"bytes32","name":"originBlockHash","internalType":"bytes32"},{"type":"uint8","name":"basefeeSharingPctg","internalType":"uint8"},{"type":"tuple[]","name":"sources","internalType":"struct IInbox.DerivationSource[]","components":[{"type":"bool","name":"isForcedInclusion","internalType":"bool"},{"type":"tuple","name":"blobSlice","internalType":"struct LibBlobs.BlobSlice","components":[{"type":"bytes32[]","name":"blobHashes","internalType":"bytes32[]"},{"type":"uint24","name":"offset","internalType":"uint24"},{"type":"uint48","name":"timestamp","internalType":"uint48"}]}]}]}]},{"type":"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":"nonpayable","outputs":[],"name":"requestWithdrawal","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"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"address","name":"_to","internalType":"address"},{"type":"uint64","name":"_amount","internalType":"uint64"}]}]
Contract Creation Code
0x610300806040523461057657610100816157978038038091610021828561061d565b8339810103126105765761003481610640565b9061004160208201610640565b9061004e60408201610640565b61005a60608301610640565b61006660808401610640565b9061007360a08501610654565b9260e061008260c08701610654565b9501519565ffffffffffff8716809703610576576040519761024089016001600160401b0381118a8210176106095760409081526001600160a01b039182168a5291811660208a0152918216908801529081166060870152166080808601919091526001600160401b0391821660a0860152911660c084015260e0830191909152611c2061010083015260b46101208301526064610140830152604b6101608301526001610180808401919091525f6101a08401819052629896806101c085015260326101e085015261020084019190915260056102208401523090915254600881901c60ff166105b45760ff8082160361057a575b5073b2c8e57eb1eb0b686b63f58e53f859bea615677b3b1561057657604080516348ed17ff60e11b815282516001600160a01b03908116600483015260208401518116602483015291830151821660448201526060830151821660648201526080830151909116608482015260a08201516001600160401b0390811660a483015260c0830151811660c483015260e083015165ffffffffffff90811660e484015261010084015181166101048401526101208401511661012483015261014083015161014483015261016083015160ff9081166101648401526101808401516101848401526101a084015161ffff9081166101a48501526101c085015183166101c48501526101e08501519092166101e484015261020084015190911661020483015261022083015116610224820152905f826102448173b2c8e57eb1eb0b686b63f58e53f859bea615677b5af490811561056b5760ff926102209261055b575b5080516001600160a01b0390811660c09081526020830151821660e0908152604080850151841661010090815260608601518516610120908152608087015190951661014090815260a08701516001600160401b039081166101609081529588015181166101809081529488015165ffffffffffff9081166101a09081529389015181166101c090815297890151166101e090815291880151610200908152958801518a16895293870151610240529086015161ffff90811661026052948601518316610280528501519091166102a052908301519091166102c0529101519091166102e0525161512e908161066982396080518181816107ce01528181610b6a0152610bbd015260a051816102c1015260c0518181816116de0152612445015260e05181818161170a0152613e66015261010051818181611739015261407d015261012051818181611768015261251801526101405181818161042a015281816117970152611b0f0152610160518181816117ce01528181611bcb0152613ea80152610180518181816117fd015261444d01526101a05181818161182b01528181611c060152611d3a01526101c05181818161185901526143eb01526101e05181818161188801526143c70152610200518181816118b001528181612ff3015281816139c601528181613a180152613cf80152610220518181816118d90152613e0e015261024051818181611901015261491a01526102605181818161192b0152818161497401526149ac01526102805181818161195b01528181611ef20152611fb001526102a05181818161198b01528181611ed10152611fd801526102c0518181816119b6015261262001526102e0518181816119e0015261494f0152f35b5f6105659161061d565b5f6102d9565b6040513d5f823e3d90fd5b5f80fd5b60ff90811916175f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a15f610178565b60405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b6064820152608490fd5b634e487b7160e01b5f52604160045260245ffd5b601f909101601f19168101906001600160401b0382119082101761060957604052565b51906001600160a01b038216820361057657565b51906001600160401b03821682036105765756fe60806040526004361015610011575f80fd5b5f3560e01c80630423c7de1461027457806304f3bcec1461026f5780630d8912f31461026a578063137658381461026557806319ab453c14610260578063226112801461025b5780632f1969b0146102565780633075db56146102515780633659cfe61461024c5780633f4ba83a1461024757806340df9866146102425780634f1ef2861461023d57806352d1902d1461023857806359db6e85146102335780635c975abb1461022e5780635ccc1718146102295780636aa6a01a14610224578063715018a61461021f57806379ba50971461021a5780638301d56d146102155780638456cb59146102105780638abf60771461020b5780638da5cb5b146102065780639791e64414610201578063a834725a146101fc578063afb63ad4146101f7578063b28e824e146101f2578063c3f909d4146101ed578063d6dad060146101e8578063dbaf2145146101e3578063df596d9e146101de578063e3053335146101d9578063e30c3978146101d4578063ea191743146101cf578063edbacd44146101ca578063efba83c9146101c5578063f2fde38b146101c05763f954ab92146101bb575f80fd5b612896565b612826565b612789565b6126e1565b61209d565b612075565b611f82565b611e6f565b611c44565b611a37565b6116b8565b611482565b61140c565b6113bc565b61127e565b6111d9565b6111a5565b611139565b610f78565b610ef4565b610e8f565b610de6565b610db6565b610d88565b610c6e565b610bab565b610b18565b610942565b61085c565b6107ac565b61077d565b6106a0565b6105c7565b6104cf565b6103b0565b61030e565b6102ac565b610287565b5f91031261028357565b5f80fd5b34610283575f36600319011261028357602065ffffffffffff60fb5416604051908152f35b34610283575f366003190112610283576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6001600160a01b0381160361028357565b359061030c826102f0565b565b3461028357602036600319011261028357604061035c600435610330816102f0565b6103386128de565b506103416128de565b506001600160a01b03165f9081526101016020526040902090565b65ffffffffffff82519161036f83610a08565b546001600160401b0381168352816020840191851c1681526001600160401b038451935116835251166020820152f35b6001600160401b0381160361028357565b34610283576020366003190112610283576004356103cd8161039f565b6103d5613408565b60025f5160206150b95f395f51905f525d33156104c0576103f98133610101614634565b335f9081526101016020526040902065ffffffffffff905460401c1661049c575b61044e61042682614688565b30337f00000000000000000000000000000000000000000000000000000000000000006146ad565b6040516001600160401b03919091168152339081907fe5e95641fa87bdfef3ce0d39f0c9a37c200f3bf59f53623b3de21e03ed33e3d290602090a360015f5160206150b95f395f51905f525d005b335f90815261010160205260409020805465ffffffffffff60401b1916905561041a565b63e6c4247b60e01b5f5260045ffd5b34610283576020366003190112610283576004356104ec816102f0565b61053a5f549161052061050a6105068560ff9060081c1690565b1590565b809481956105b9575b8115610599575b506128f6565b82610531600160ff195f5416175f55565b61058257613492565b61054057005b61054e5f5461ff0019165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1005b6105946101005f5461ff001916175f55565b613492565b303b159150816105ab575b505f61051a565b60ff1660011490505f6105a4565b600160ff8216109150610513565b34610283575f366003190112610283576105df613408565b60025f5160206150b95f395f51905f525d335f9081526101016020526040902065ffffffffffff815460401c161561065957805465ffffffffffff60401b19169055337fc51fdb96728de385ec7859819e3997bc618362ef0dbca0ad051d856866cda3db5f80a260015f5160206150b95f395f51905f525d005b6387bdc6a960e01b5f5260045ffd5b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90602061069d928181520190610668565b90565b346102835760a0366003190112610283576107796040516106c081610a23565b6004356106cc816108c7565b815261076c6106da36611dd3565b6020830190815261076661075e61074f6040608435946106f986612959565b818801958652610707612a31565b9765ffffffffffff60d01b905160d01b16602089015261ffff60f01b81515160f01b16602689015261ffff60f01b60208251015160f01b16602889015251015162ffffff1690565b60e81b602a860152602d850190565b915160ff1690565b906146f6565b506040519182918261068c565b0390f35b34610283575f366003190112610283576020600260ff5f5160206150b95f395f51905f525c1614604051908152f35b34610283576020366003190112610283576004356107c9816102f0565b6108207f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166108023082141561296f565b5f5160206150d95f395f51905f52546001600160a01b0316146129d0565b61082861396c565b6040516108559161083a602083610a59565b5f8252601f196108495f610ac7565b0136602084013761358a565b005b6109f4565b34610283575f36600319011261028357610886610881600260ff60c95460081c161490565b613712565b61010060c95461ff0019161760c9557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a161085561396c565b65ffffffffffff81160361028357565b359061030c826108c7565b9060608101918051926060835283518091526020608084019401905f5b81811061092c5750505065ffffffffffff60408262ffffff60208395015116602086015201511691015290565b82518652602095860195909201916001016108ff565b3461028357604036600319011261028357610974600435610962816108c7565b6024359061096f826108c7565b6138a2565b6040518091602082016020835281518091526040830190602060408260051b8601019301915f905b8282106109ab57505050500390f35b919360019193955060206109e48192603f198a82030186526040838a516001600160401b038151168452015191818582015201906108e2565b960192019201859493919261099c565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761085757604052565b606081019081106001600160401b0382111761085757604052565b60c081019081106001600160401b0382111761085757604052565b90601f801991011681019081106001600160401b0382111761085757604052565b6040519061030c61012083610a59565b6040519061030c61024083610a59565b6040519061030c606083610a59565b6040519061030c60e083610a59565b6040519061030c604083610a59565b6001600160401b03811161085757601f01601f191660200190565b929192610aee82610ac7565b91610afc6040519384610a59565b829481845281830111610283578281602093845f960137010152565b604036600319011261028357600435610b30816102f0565b602435906001600160401b038211610283573660238301121561028357610b64610855923690602481600401359101610ae2565b90610b9e7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166108023082141561296f565b610ba661396c565b613652565b34610283575f366003190112610283577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163003610c03576040515f5160206150d95f395f51905f528152602090f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b3461028357602036600319011261028357600435610c8a61396c565b65ffffffffffff60fb541660405190633dd0723360e21b825282600483015260248201525f8160448173b2c8e57eb1eb0b686b63f58e53f859bea615677b5af4918215610d8357610d3d61057d927fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d2945f905f5f925f92610d4d575b610d3893945090610d2e610d339265ffffffffffff1665ffffffffffff1960fb54161760fb55565b612db0565b6139c4565b613ac0565b6040519081529081906020820190565b50505050610d38610d2e610d75610d33933d805f833e610d6d8183610a59565b810190612ce6565b909550859450925090610d06565b612da5565b34610283575f366003190112610283576020610dac600260ff60c95460081c161490565b6040519015158152f35b34610283575f3660031901126102835760406101005465ffffffffffff825191818116835260301c166020820152f35b34610283575f366003190112610283575f60a0604051610e0581610a3e565b828152826020820152826040820152826060820152826080820152015260c0610e2c612e43565b60a06040519165ffffffffffff815116835265ffffffffffff602082015116602084015265ffffffffffff604082015116604084015265ffffffffffff606082015116606084015265ffffffffffff6080820151166080840152015160a0820152f35b34610283575f36600319011261028357610ea761396c565b606580546001600160a01b03199081169091556033805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610283575f36600319011261028357606554336001600160a01b0390911603610f215761085533613b46565b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b34610283576020366003190112610283576004356001600160401b03811161028357604060031982360301126102835760405190610fb582610a08565b80600401356001600160401b038111610283576024610fdc60209260043691860101612f42565b92838552013592610fec84612abd565b0191825260c08101906110af61109261101261100d855151603a0260830190565b612a53565b9260a061108761107561105c61104f61104360208a01611038885165ffffffffffff1690565b60d01b815260060190565b60208781015182520190565b6040860151815260200190565b60608501516001600160a01b031660601b815260140190565b608084015165ffffffffffff16611038565b910151815260200190565b61109d845151614865565b83515161ffff1660f01b815260020190565b905f915b83518051841015611113576001916110ce8561110b93613303565b51805160601b6bffffffffffffffffffffffff19168252602081015160d01b6001600160d01b031916601483015260400151601a820152603a0190565b9201916110b3565b6107798361076c846111258a51151590565b15611132576001906146f6565b5f906146f6565b34610283575f3660031901126102835761116461115e600260ff60c95460081c161490565b15613712565b61020060c95461ff0019161760c9557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a161085561396c565b34610283575f366003190112610283575f5160206150d95f395f51905f52546040516001600160a01b039091168152602090f35b34610283575f366003190112610283576033546040516001600160a01b039091168152602090f35b9181601f84011215610283578235916001600160401b038311610283576020838186019501011161028357565b6040600319820112610283576004356001600160401b038111610283578161125891600401611201565b92909291602435906001600160401b0382116102835761127a91600401611201565b9091565b34610283576112bd6112b86112923661122e565b6112a0959395949294613408565b60025f5160206150b95f395f51905f525d3691610ae2565b613b99565b65ffffffffffff81511680159081156113b1575b50156113a25765ffffffffffff60016113336113509361139a9660fc54906112fe8265ffffffffffff1690565b978891611320603085901c65ffffffffffff169460601c65ffffffffffff1690565b9461132e8985161515612fc7565b613cbd565b93011665ffffffffffff1665ffffffffffff1960fc54161760fc55565b60fc80546bffffffffffff00000000000019164360301b6bffffffffffff00000000000016179055610d3861138b825165ffffffffffff1690565b61139483613f08565b90613a16565b610855614621565b63559895a360e01b5f5260045ffd5b90504211155f6112d1565b346102835760203660031901126102835760206113da600435612ff1565b604051908152f35b602060031982011261028357600435906001600160401b0382116102835761127a91600401611201565b346102835760a06114326112b8611422366113e2565b61142a61304c565b503691610ae2565b60ff604080519265ffffffffffff81511684526114786020820151602086019062ffffff6040809261ffff815116855261ffff6020820151166020860152015116910152565b0151166080820152f35b34610283576020366003190112610283576004356001600160401b038111610283576101206003198236030112610283576114bb610a7a565b906114c8816004016108d7565b82526114d6602482016108d7565b60208301526114e7604482016108d7565b60408301526114f860648201610301565b60608301526084810135608083015261151360a482016108d7565b60a083015260c481013560c083015261152e60e48201612964565b60e0830152610104810135916001600160401b0383116102835761155e610d3d9260046107799536920101613071565b610100820152613f08565b81516001600160a01b031681526102408101929161030c91906102209081906020818101516001600160a01b0316908501526040818101516001600160a01b0316908501526060818101516001600160a01b0316908501526080818101516001600160a01b03169085015260a0818101516001600160401b03169085015260c0818101516001600160401b03169085015260e08181015165ffffffffffff16908501526101008181015165ffffffffffff16908501526101208181015165ffffffffffff169085015261014081015161014085015261165461016082015161016086019060ff169052565b6101808101516101808501526116776101a08201516101a086019061ffff169052565b6101c0818101516001600160401b0316908501526101e0818101516001600160401b0316908501526102008181015161ffff1690850152015160ff16910152565b34610283575f366003190112610283576116d06131d4565b506107796116dc610a8a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660408201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660608201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031660808201526001600160401b037f00000000000000000000000000000000000000000000000000000000000000001660a08201526001600160401b037f00000000000000000000000000000000000000000000000000000000000000001660c082015265ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660e082015265ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001661010082015265ffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166101208201527f000000000000000000000000000000000000000000000000000000000000000061014082015260ff7f0000000000000000000000000000000000000000000000000000000000000000166101608201527f000000000000000000000000000000000000000000000000000000000000000061018082015261ffff7f0000000000000000000000000000000000000000000000000000000000000000166101a08201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000166101c08201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000166101e082015261ffff7f00000000000000000000000000000000000000000000000000000000000000001661020082015260ff7f00000000000000000000000000000000000000000000000000000000000000001661022082015260405191829182611569565b604090600319011261028357600435611a2a816102f0565b9060243561069d8161039f565b3461028357611a4536611a12565b90611a4e613408565b60025f5160206150b95f395f51905f525d6001600160a01b038116156104c057335f90815261010160205260409020611b339190611aeb611acb8254611a9a816001600160401b031690565b6001600160401b03811697886001600160401b038216115f14611c3357508092839265ffffffffffff9060401c1690565b65ffffffffffff811615908115611bfb575b50611bb3575b505033614b73565b936001600160401b0385161480611b8e575b611b78575b50611b0c83614688565b907f0000000000000000000000000000000000000000000000000000000000000000614be9565b6040516001600160401b03909116815233907f3362c96009316515fccd3dd29c7036c305ad9e892d83dd5681845ac9edb0c9a89080602081015b0390a2610855614621565b805465ffffffffffff60401b191690555f611b02565b508054611bac9060401c65ffffffffffff165b65ffffffffffff1690565b1515611afd565b611bf491611bc091613ffe565b6001600160401b03807f0000000000000000000000000000000000000000000000000000000000000000169116101561401e565b805f611ae3565b611c2b9150611ba1907f000000000000000000000000000000000000000000000000000000000000000090613fdb565b42105f611add565b92839260401c65ffffffffffff1690565b34610283575f36600319011261028357611c5c613408565b60025f5160206150b95f395f51905f525d335f90815261010160205260409020611c85906133db565b6001600160401b03611c9e82516001600160401b031690565b1615611dac57602081019065ffffffffffff611cc0835165ffffffffffff1690565b16611d9d574265ffffffffffff16909152611d2b90335f90815261010160205260409020815181546020909301516dffffffffffff000000000000000060409190911b166dffffffffffffffffffffffffffff199093166001600160401b0390911617919091179055565b611d60611ba165ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001642614034565b60405165ffffffffffff909116815233907f3bbe41cfdd142e0f9b2224dac18c6efd2a6966e35a9ec23ab57ce63a60b33604908060208101611b6d565b63fb52063b60e01b5f5260045ffd5b634555262b60e01b5f5260045ffd5b62ffffff81160361028357565b359061030c82611dbb565b60609060231901126102835760405190611dec82610a23565b8160243561ffff8116810361028357815260443561ffff81168103610283576020820152604060643591611e1f83611dbb565b0152565b60609060031901126102835760405190611e3c82610a23565b8160043561ffff8116810361028357815260243561ffff81168103610283576020820152604060443591611e1f83611dbb565b606036600319011261028357611f1a6020611e8936611e23565b60015f5260fe602052611ebe7f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b7541515613252565b604051809381926312b2aa9160e31b83527f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060048501613277565b0381738bbdf7b3d44c1cf6aa64db449e93ad5c0d10e63c5af4908115610d83575f91611f53575b5080611f4957005b6108559033614041565b611f75915060203d602011611f7b575b611f6d8183610a59565b810190613268565b5f611f41565b503d611f63565b34610283575f366003190112610283576040516343c3d71960e01b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000166044820152602081606481738bbdf7b3d44c1cf6aa64db449e93ad5c0d10e63c5af48015610d8357610779915f91612046575b506040516001600160401b0390911681529081906020820190565b612068915060203d60201161206e575b6120608183610a59565b8101906132c8565b5f61202b565b503d612056565b34610283575f366003190112610283576065546040516001600160a01b039091168152602090f35b34610283576120ab3661122e565b926120d16120cc6120bb3361407b565b926120c4612e43565b953691610ae2565b614183565b80516120dd81866142d9565b919365ffffffffffff83169788155f1461265a57612132602080870151935b61210c60a0850195865114613317565b60408801996121258b5161211f89612ff1565b1461332d565b1561264b575b0151151590565b9283156125ff575b83612511575b5f99600188146124bb575b5065ffffffffffff16604082018190529165ffffffffffff4216606083015260c08601968751905f190161217e91613303565b5160400151905261218e90612db0565b8351606080860180516040805165ffffffffffff9586168082529890980185166020890152949093169386019390935292151592840192909252916001600160a01b03909116907f7ca0f1e30099488c4ee24e86a6b2c6802e9add6d530919af7aa17db3bcc1cff190608090a261220482614489565b936040518061221f8782919060206040840193600181520152565b035f5160206150995f395f51905f5291a18251604080516002815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a1602083015160405161228b819282919060206040840193600381520152565b035f5160206150995f395f51905f5291a1516040516122b7819282919060206040840193600481520152565b035f5160206150995f395f51905f5291a15160408051600581526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a16080810151604080516006815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a160a00151604051612361819282919060206040840193600781520152565b035f5160206150995f395f51905f5291a1805161237d906132f1565b516040015160405161239c819282919060206040840193600881520152565b035f5160206150995f395f51905f5291a180516123b8906132f1565b515160408051600981526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a1516123ff906132f1565b5160209081015160408051600b815265ffffffffffff909216928201929092527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b147749190a17f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15610283575f93612497604051968795869485946314bcf3dd60e01b865260048601613363565b03915afa8015610d83576124a757005b806124b55f61085593610a59565b80610279565b65ffffffffffff919a506124ec611ba160206124de6125089460c08c0151613303565b51015165ffffffffffff1690565b612502611ba1606086015165ffffffffffff1690565b90614477565b4203999061214b565b60808601517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169065ffffffffffff169060a0880151604061256360c08b01515f198d0190613303565b51015161257f612571610a9a565b65ffffffffffff9095168552565b60208401526040830152803b156102835760408051631934171960e31b8152835165ffffffffffff1660048201526020840151602482015292015160448301525f908290606490829084905af18015610d83576125eb575b504265ffffffffffff166080830152612140565b806124b55f6125f993610a59565b5f6125d7565b925065ffffffffffff61261b608083015165ffffffffffff1690565b61ffff7f00000000000000000000000000000000000000000000000000000000000000001601164210159261213a565b6126558789614391565b61212b565b6121326020604061267b60c089015165ffffffffffff5f198a011690613303565b510151936120fc565b90602080835192838152019201905f5b8181106126a15750505090565b825180516001600160a01b0316855260208181015165ffffffffffff16818701526040918201519186019190915260609094019390920191600101612694565b34610283576126fd6120cc6126f5366113e2565b61142a61337f565b604051809160208252610779602061277d60c0845160408488015265ffffffffffff8151166060880152838101516080880152604081015160a088015260018060a01b036060820151168288015265ffffffffffff60808201511660e088015260a0810151610100880152015160e0610120870152610140860190612684565b92015115156040840152565b346102835761279736611a12565b61279f613408565b60025f5160206150b95f395f51905f525d6001600160a01b0382169182156104c057816127ce91610101614634565b6127da61042682614688565b6040516001600160401b0391909116815233907fe5e95641fa87bdfef3ce0d39f0c9a37c200f3bf59f53623b3de21e03ed33e3d290602090a360015f5160206150b95f395f51905f525d005b3461028357602036600319011261028357600435612843816102f0565b61284b61396c565b606580546001600160a01b0319166001600160a01b039283169081179091556033549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b34610283576020366003190112610283576004356001600160401b0381116102835760e06003198236030112610283576113da6128d96020923690600401612f42565b614489565b604051906128eb82610a08565b5f6020838281520152565b156128fd57565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b60ff81160361028357565b359061030c82612959565b1561297657565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b156129d757565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b60408051909190612a428382610a59565b600e815291601f1901366020840137565b90612a5d82610ac7565b612a6a6040519182610a59565b8281528092612a7b601f1991610ac7565b0190602036910137565b519061030c826108c7565b519061030c826102f0565b519061030c82612959565b6001600160401b0381116108575760051b60200190565b8015150361028357565b519061030c82611dbb565b9080601f83011215610283578151612ae981612aa6565b92612af76040519485610a59565b81845260208085019260051b820101908382116102835760208101925b828410612b2357505050505090565b83516001600160401b0381116102835782016040818703601f1901126102835760405190612b5082610a08565b6020810151612b5e81612abd565b825260408101516001600160401b0381116102835760209101016060818803126102835760405190612b8f82610a23565b80516001600160401b03811161028357810188601f8201121561028357805190612bb882612aa6565b91612bc66040519384610a59565b80835260208084019160051b830101918b831161028357602001905b828210612c255750505091612c11604060209694938796948452612c07878201612ac7565b8785015201612a85565b604082015283820152815201930192612b14565b8151815260209182019101612be2565b9190916101208184031261028357612c4b610a7a565b92612c5582612a85565b8452612c6360208301612a85565b6020850152612c7460408301612a85565b6040850152612c8560608301612a90565b606085015260808201516080850152612ca060a08301612a85565b60a085015260c082015160c0850152612cbb60e08301612a9b565b60e08501526101008201516001600160401b03811161028357612cde9201612ad2565b610100830152565b8082039261012084126102835760c08251612d00816108c7565b94601f19011261028357604051612d1681610a3e565b6020830151612d24816108c7565b81526040830151612d34816108c7565b60208201526060830151612d47816108c7565b60408201526080830151612d5a816108c7565b606082015260a0830151612d6d816108c7565b608082015260c083015160a08201529260e08301516001600160401b0381116102835761010091612d9f918501612c35565b92015190565b6040513d5f823e3d90fd5b805160fc805460208401516040850151606080870151608088015165ffffffffffff60c01b60c09190911b166001600160f01b031990951665ffffffffffff909716969096176bffffffffffff00000000000060309490941b9390931692909217911b65ffffffffffff60601b161760909390931b65ffffffffffff60901b169290921791909117905560a0015160fd55565b60405190612e5082610a3e565b81612e9b65ffffffffffff60fc548181168452818160301c166020850152818160601c16604085015281808260901c1616606085015260c01c16608083019065ffffffffffff169052565b60a060fd54910152565b81601f8201121561028357803590612ebc82612aa6565b92612eca6040519485610a59565b8284526020606081860194028301019181831161028357602001925b828410612ef4575050505090565b606084830312610283576020606091604051612f0f81610a23565b8635612f1a816102f0565b815282870135612f29816108c7565b8382015260408701356040820152815201930192612ee6565b91909160e08184031261028357612f57610aa9565b92612f61826108d7565b84526020820135602085015260408201356040850152612f8360608301610301565b6060850152612f94608083016108d7565b608085015260a082013560a085015260c08201356001600160401b03811161028357612fc09201612ea5565b60c0830152565b15612fce57565b63ba74d80f60e01b5f5260045ffd5b634e487b7160e01b5f52601260045260245ffd5b7f000000000000000000000000000000000000000000000000000000000000000090811561302957065f5260fe60205260405f205490565b612fdd565b6040519061303b82610a23565b5f6040838281528260208201520152565b6040519061305982610a23565b5f60408382815261306861302e565b60208201520152565b9080601f8301121561028357813561308881612aa6565b926130966040519485610a59565b81845260208085019260051b820101908382116102835760208101925b8284106130c257505050505090565b83356001600160401b0381116102835782016040818703601f19011261028357604051906130ef82610a08565b60208101356130fd81612abd565b825260408101356001600160401b038111610283576020910101606081880312610283576040519061312e82610a23565b80356001600160401b03811161028357810188601f820112156102835780359061315782612aa6565b916131656040519384610a59565b80835260208084019160051b830101918b831161028357602001905b8282106131c457505050916131b06040602096949387969484526131a6878201611dc8565b87850152016108d7565b6040820152838201528152019301926130b3565b8135815260209182019101613181565b6131dc610a8a565b905f82525f60208301525f60408301525f60608301525f60808301525f60a08301525f60c08301525f60e08301525f6101008301525f6101208301525f6101408301525f6101608301525f6101808301525f6101a08301525f6101c08301525f6101e08301525f6102008301525f610220830152565b1561325957565b63f37a8b1360e01b5f5260045ffd5b90816020910312610283575190565b6060906001600160401b0361030c94969593968160c084019860ff8552166020840152166040820152019062ffffff6040809261ffff815116855261ffff6020820151166020860152015116910152565b90816020910312610283575161069d8161039f565b634e487b7160e01b5f52603260045260245ffd5b8051156132fe5760200190565b6132dd565b80518210156132fe5760209160051b010190565b1561331e57565b63198070b360e01b5f5260045ffd5b1561333457565b63f904c2fd60e01b5f5260045ffd5b908060209392818452848401375f828201840152601f01601f1916010190565b61069d9492606092825260208201528160408201520191613343565b6040519061338c82610a08565b60405160e08101836001600160401b03821183831017610857575f9260209260405283815283838201528360408201528360608201528360808201528360a0820152606060c082015281520152565b906040516133e881610a08565b91546001600160401b038116835260401c65ffffffffffff166020830152565b600260ff5f5160206150b95f395f51905f525c161461342357565b63dfc60d8560e01b5f5260045ffd5b1561343957565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b6134ab60ff5f5460081c166134a681613432565b613432565b6001600160a01b0381166134d457506134c333613b46565b61010060c95461ff0019161760c955565b6134c390613b46565b156134e457565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b906135b67f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b156135c5575061030c906147bd565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281613631575b5061360f5760405162461bcd60e51b81528061360b6004820161353b565b0390fd5b61030c9261362c5f5160206150d95f395f51905f525f94146134dd565b6146ff565b61364b91935060203d602011611f7b57611f6d8183610a59565b915f6135ed565b9061367e7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b1561368d575061030c906147bd565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f92816136f1575b506136d35760405162461bcd60e51b81528061360b6004820161353b565b61030c9261362c5f5160206150d95f395f51905f52600194146134dd565b61370b91935060203d602011611f7b57611f6d8183610a59565b915f6136b5565b1561371957565b63bae6e2a960e01b5f5260045ffd5b6040519061373582610a23565b5f604083606081528260208201520152565b6040519061375482610a08565b815f81526020613762613728565b910152565b60405190613776602083610a59565b5f80835282815b82811061378957505050565b602090613794613747565b8282850101520161377d565b906137aa82612aa6565b6137b76040519182610a59565b82815280926137c8601f1991612aa6565b01905f5b8281106137d857505050565b6020906137e3613747565b828285010152016137cc565b906040516137fc81610a23565b80926040518060208354918281520190835f5260205f20905f5b81811061386357505050600161030c949383613839604095613856950382610a59565b8552015462ffffff8116602085015260181c65ffffffffffff1690565b65ffffffffffff16910152565b8254845260209093019260019283019201613816565b9060405161388681610a08565b6020613762600183956001600160401b038154168552016137ef565b6101005465ffffffffffff8281169493603083901c821693929091168510801561395a575b801561394a575b61393d576138e9929165ffffffffffff809216920316614859565b6138f2816137a0565b925f5b82811061390157505050565b8061392161391c846001940160ff905f5260205260405f2090565b613879565b61392b8288613303565b526139368187613303565b50016138f5565b505050905061069d613767565b5065ffffffffffff8116156138ce565b5065ffffffffffff83168510156138c7565b6033546001600160a01b0316330361398057565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b7f000000000000000000000000000000000000000000000000000000000000000015613029575f805260fe6020527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af55565b7f00000000000000000000000000000000000000000000000000000000000000009081156130295765ffffffffffff16065f5260fe60205260405f2055565b9080602083519182815201916020808360051b8301019401925f915b838310613a8057505050505090565b9091929394602080613ab1600193601f198682030187526040838b51805115158452015191818582015201906108e2565b97019301930191939290613a71565b65ffffffffffff8151167f7c4c4523e17533e451df15762a093e0693a2cd8b279fe54c6cd3777ed577121360018060a01b03606084015116926080810151613b4165ffffffffffff6040840151169261010060ff60e08301511691015190604051948594855260208501526040840152608060608401526080830190613a55565b0390a3565b606580546001600160a01b0319908116909155603380549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b9060ff602d613ba661304c565b93602081015160d01c8552602681015160f01c6020860190815152602882015160f01c6020825101526040602a83015160e81c91510152016001815160f81c915050166040830152565b6040519061012082018281106001600160401b03821117610857576040526060610100835f81525f60208201525f60408201525f838201525f60808201525f60a08201525f60c08201525f60e08201520152565b15613c4b57565b6349517a1d60e11b5f5260045ffd5b15613c6157565b63eaabac9b60e01b5f5260045ffd5b90816020910312610283575161069d816108c7565b6001600160a01b03909116815260406020820181905261069d93910191613343565b15613cae57565b63e92c469f60e01b5f5260045ffd5b9294613d1c90613ce365ffffffffffff613d239497613cda613bf0565b50164311613c44565b5f1965ffffffffffff918803821681019091167f0000000000000000000000000000000000000000000000000000000000000000030190565b1515613c5a565b613d7c613d536020613d4b613d45613d3f604088015160ff1690565b60ff1690565b336148ad565b940151614a44565b613d5b610ab8565b905f8252602082015283515f1981510191613d768383613303565b52613303565b505f92613d8f6105066020850151151590565b613e3c575b50505f19430190613deb613db265ffffffffffff5f19870116612ff1565b915193613dce613dc0610a7a565b65ffffffffffff9097168752565b4265ffffffffffff16602087015265ffffffffffff166040860152565b336060850152608084015265ffffffffffff811660a08401524060c083015260ff7f00000000000000000000000000000000000000000000000000000000000000001660e083015261010082015290565b604051635600026d60e11b815292935060209183918291613e61913360048501613c85565b03815f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af1908115610d83575f91613ed9575b5090613ed2613ecd7f000000000000000000000000000000000000000000000000000000000000000033614b2d565b613ca7565b5f80613d94565b613efb915060203d602011613f01575b613ef38183610a59565b810190613c70565b5f613e9e565b503d613ee9565b604051613fc181613fb3610100602083019560208752613f3360408501825165ffffffffffff169052565b602081015165ffffffffffff166060850152604081015165ffffffffffff16608085015260608101516001600160a01b031660a0850152608081015160c085015260a081015165ffffffffffff1660e085015260c08101518483015260e081015160ff166101208501520151610120610140840152610160830190613a55565b03601f198101835282610a59565b51902090565b634e487b7160e01b5f52601160045260245ffd5b9065ffffffffffff8091169116019065ffffffffffff8211613ff957565b613fc7565b906001600160401b03809116911603906001600160401b038211613ff957565b1561402557565b6321f68cc160e21b5f5260045ffd5b91908201809211613ff957565b61030c915a91614c3a565b91908260409103126102835760208251612d9f81612abd565b1561406c57565b63c1a58f1960e01b5f5260045ffd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690811561412e5760408051633326844b60e11b81526001600160a01b0390921660048301529091829060249082905afa8015610d83575f915f916140fd575b50156140f8576140f390614065565b600190565b505f90565b9050614121915060403d604011614127575b6141198183610a59565b81019061404c565b5f6140e4565b503d61410f565b50505f90565b9061413e82612aa6565b61414b6040519182610a59565b828152809261415c601f1991612aa6565b01905f5b82811061416c57505050565b60209061417761302e565b82828501015201614160565b9061ffff6142476142336141cf61421f6142126141fe6141ea6141d96141cf6141be60206141af61337f565b9d01906006825160d01c920190565b91908d519065ffffffffffff169052565b9060208251920190565b9060208c5101529060208251920190565b9060408b510152906014825160601c920190565b919060608a51019060018060a01b03169052565b906006825160d01c920190565b919060808851019065ffffffffffff169052565b9060a086510152906002825160f01c920190565b911661425281614134565b60c0855101525f905b8082106142715750505160f81c15156020830152565b909161427e600191614c7d565b939061428f8260c089510151613303565b52019061425b565b1561429e57565b6363db3a4160e01b5f5260045ffd5b156142b457565b63677c56f160e01b5f5260045ffd5b156142ca57565b63181432e760e11b5f5260045ffd5b909165ffffffffffff60018160408501511601169260c08101515193841561438257614375611ba1836143288465ffffffffffff61432061069d985165ffffffffffff1690565b161115614297565b61435d614356611ba15f198b614347611ba1875165ffffffffffff1690565b0101995165ffffffffffff1690565b88106142ad565b614369848810156142c3565b5165ffffffffffff1690565b900365ffffffffffff1690565b63c2e5347d60e01b5f5260045ffd5b60c081019161441165ffffffffffff60206143b182875195168095613303565b5101511665ffffffffffff808060fc5460901c167f00000000000000000000000000000000000000000000000000000000000000000116917f00000000000000000000000000000000000000000000000000000000000000000116614477565b42111561447257606061443c61442e61444b9361030c9651613303565b51516001600160a01b031690565b9201516001600160a01b031690565b7f000000000000000000000000000000000000000000000000000000000000000091614cab565b505050565b9080821115614484575090565b905090565b60c081015180519061455160a06144b56003850260090190604051828193825260010160051b01604052565b602080820152946144db6144d2611ba1835165ffffffffffff1690565b60408801528690565b5060208101516060870152604081015160808701526060810151614522906145199061450d906001600160a01b031681565b6001600160a01b031690565b60a08801528690565b5061454561453c611ba1608084015165ffffffffffff1690565b60c08801528690565b50015160e08501528390565b5060e061010084015261012083018290525f9060095b83831061459f575050505061069d614586826020815160051b91012090565b918051604051828260010160051b011490151060061b52565b600360019161461760406145b38787613303565b5180516145dc906145ce9061450d906001600160a01b031681565b6001860160051b8c01528a90565b506146066145f6611ba1602084015165ffffffffffff1690565b60018689010160051b8c01528a90565b5001516003830160051b8901528790565b5001920191614567565b60015f5160206150b95f395f51905f525d565b6001600160a01b039091165f90815260209190915260409020906001600160401b03808354169116016001600160401b038111613ff957815467ffffffffffffffff19166001600160401b03909116179055565b6001600160401b0316633b9aca00810290808204633b9aca001490151715613ff95790565b6040516323b872dd60e01b60208201526001600160a01b03928316602482015292909116604483015260648083019390935291815261030c916146f1608483610a59565b614da9565b60019181530190565b91614709836147bd565b6001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2815115908115916147b5575b5061474c575050565b6147b2915f8060405193614761606086610a59565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020860152660819985a5b195960ca1b6040860152602081519101845af46147ac614fd0565b91614fff565b50565b90505f614743565b803b156147fe5760018060a01b03166bffffffffffffffffffffffff60a01b5f5160206150d95f395f51905f525416175f5160206150d95f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b81811115614484575090565b61ffff1061486f57565b63161e7a6b60e11b5f5260045ffd5b6040519061488b82610a08565b5f602083606081520152565b1561489e57565b63014b3fdb60e11b5f5260045ffd5b919065ffffffffffff61030c916148c261487e565b94610100546148e86148d98265ffffffffffff1690565b9160301c65ffffffffffff1690565b916149158583850316918286115f146149e757829384915b61490c600184016137a0565b90818d52614e95565b9290947f00000000000000000000000000000000000000000000000000000000000000001191826149dd575b505061499f575b50501660ff7f00000000000000000000000000000000000000000000000000000000000000001661ffff7f000000000000000000000000000000000000000000000000000000000000000016020142116020840152565b6105066149d1916149d6937f000000000000000000000000000000000000000000000000000000000000000091614f92565b614897565b5f80614948565b1190505f80614941565b85938491614900565b156149f757565b63fdac229f60e01b5f5260045ffd5b90614a1082612aa6565b614a1d6040519182610a59565b8281528092612a7b601f1991612aa6565b15614a3557565b637bb2fa2f60e11b5f5260045ffd5b90614a4d613728565b506020820191614a6d61ffff614a65855161ffff1690565b1615156149f0565b614a8b614a86614a7f855161ffff1690565b61ffff1690565b614a06565b915f5b614a9d614a7f865161ffff1690565b811015614aef57614a7f600182614ac5614a9d94614ac0614a7f895161ffff1690565b614034565b49614ad08289613303565b52614ae6614ade8289613303565b511515614a2e565b01915050614a8e565b509250614b056040614b1c92015162ffffff1690565b614b0d610a9a565b92835262ffffff166020830152565b4265ffffffffffff16604082015290565b60018060a01b03165f526101016020526001600160401b0360405f205491166001600160401b03821610159081614b62575090565b65ffffffffffff915060401c161590565b6001600160a01b03165f9081526101016020526040902080549092916001600160401b039182169181168211614bc15750506001600160401b03825416916001600160401b03198154169055565b92614bcf8461030c93613ffe565b6001600160401b03166001600160401b0319825416179055565b60405163a9059cbb60e01b60208201526001600160a01b03909216602483015260448083019390935291815261030c916146f1606483610a59565b15614c2b57565b634c67134d60e11b5f5260045ffd5b919080156144725761030c925f92839260405192614c59602085610a59565b848452614c706001600160a01b0382161515614c24565b60208451940192f1614c24565b614c8561302e565b91815160601c8352601482015160d01c6020840152603a601a8301519201916040840152565b6001600160a01b0381165f908152610101602052604090209092919080546001600160401b039081169084168111614d945750805467ffffffffffffffff1981169091556001600160401b03165b6001600160401b03811615614d8e577faa22f5157944b5fa6846460e159d57ea9c3878e71fda274af372fa2ccf285aa0916001600160401b0382614d4d677fffffffffffffff60609560011c168092613ffe565b9080614d7c575b60408051978416885260208801919091529116908501526001600160a01b03908116941692a3565b614d898185610101614634565b614d54565b50505050565b90614da490614bcf858094613ffe565b614cf9565b90614e039160018060a01b03165f8060405193614dc7604086610a59565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af16147ac614fd0565b8051908115918215614e71575b505015614e1957565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b9091506020908201829003126102835760200151614e8e81612abd565b5f80614e10565b939190938315614f84575f5f5b858110614f0a575060406020614ed565ffffffffffff969798614ed08896633b9aca00614ee5970290614041565b6132f1565b510151015165ffffffffffff1690565b941601169061030c826101009065ffffffffffff1665ffffffffffff19825416179055565b90600190614f7c614f70614f318565ffffffffffff89160160ff905f5260205260405f2090565b614f39610ab8565b60018152614f488683016137ef565b6020820152614f57878d613303565b52614f62868c613303565b50546001600160401b031690565b6001600160401b031690565b019101614ea2565b5065ffffffffffff93509150565b65ffffffffffff8091169116811461412e575f5260ff60205265ffffffffffff600260405f20015460181c1690811561412e5761ffff160142101590565b3d15614ffa573d90614fe182610ac7565b91614fef6040519384610a59565b82523d5f602084013e565b606090565b919290156150615750815115615013575090565b3b1561501c5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156150745750805190602001fd5b60405162461bcd60e51b81526020600482015290819061360b90602483019061066856fe712de588b76f7fdb47439ab8677a0c8233392168ef0308d402c7b8d72138a080a5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220f86c43e17817ce316cd3d772eaca06b07592db2cfd160e26ed1e615a9f74846a64736f6c634300081e0033000000000000000000000000461461e95de3cc306d5424f554463c162433384e000000000000000000000000cfb57e95cbab87bfd167b3eddd5c11e2d1613b2200000000000000000000000053789e39e3310737e8c8ced483032aac25b39ded000000000000000000000000cbf1639b8809adff74bd59ec292e436107852cc9000000000000000000000000a20182131658295f37c1a1efdbdc89eff97d9c58000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x60806040526004361015610011575f80fd5b5f3560e01c80630423c7de1461027457806304f3bcec1461026f5780630d8912f31461026a578063137658381461026557806319ab453c14610260578063226112801461025b5780632f1969b0146102565780633075db56146102515780633659cfe61461024c5780633f4ba83a1461024757806340df9866146102425780634f1ef2861461023d57806352d1902d1461023857806359db6e85146102335780635c975abb1461022e5780635ccc1718146102295780636aa6a01a14610224578063715018a61461021f57806379ba50971461021a5780638301d56d146102155780638456cb59146102105780638abf60771461020b5780638da5cb5b146102065780639791e64414610201578063a834725a146101fc578063afb63ad4146101f7578063b28e824e146101f2578063c3f909d4146101ed578063d6dad060146101e8578063dbaf2145146101e3578063df596d9e146101de578063e3053335146101d9578063e30c3978146101d4578063ea191743146101cf578063edbacd44146101ca578063efba83c9146101c5578063f2fde38b146101c05763f954ab92146101bb575f80fd5b612896565b612826565b612789565b6126e1565b61209d565b612075565b611f82565b611e6f565b611c44565b611a37565b6116b8565b611482565b61140c565b6113bc565b61127e565b6111d9565b6111a5565b611139565b610f78565b610ef4565b610e8f565b610de6565b610db6565b610d88565b610c6e565b610bab565b610b18565b610942565b61085c565b6107ac565b61077d565b6106a0565b6105c7565b6104cf565b6103b0565b61030e565b6102ac565b610287565b5f91031261028357565b5f80fd5b34610283575f36600319011261028357602065ffffffffffff60fb5416604051908152f35b34610283575f366003190112610283576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b6001600160a01b0381160361028357565b359061030c826102f0565b565b3461028357602036600319011261028357604061035c600435610330816102f0565b6103386128de565b506103416128de565b506001600160a01b03165f9081526101016020526040902090565b65ffffffffffff82519161036f83610a08565b546001600160401b0381168352816020840191851c1681526001600160401b038451935116835251166020820152f35b6001600160401b0381160361028357565b34610283576020366003190112610283576004356103cd8161039f565b6103d5613408565b60025f5160206150b95f395f51905f525d33156104c0576103f98133610101614634565b335f9081526101016020526040902065ffffffffffff905460401c1661049c575b61044e61042682614688565b30337f000000000000000000000000a20182131658295f37c1a1efdbdc89eff97d9c586146ad565b6040516001600160401b03919091168152339081907fe5e95641fa87bdfef3ce0d39f0c9a37c200f3bf59f53623b3de21e03ed33e3d290602090a360015f5160206150b95f395f51905f525d005b335f90815261010160205260409020805465ffffffffffff60401b1916905561041a565b63e6c4247b60e01b5f5260045ffd5b34610283576020366003190112610283576004356104ec816102f0565b61053a5f549161052061050a6105068560ff9060081c1690565b1590565b809481956105b9575b8115610599575b506128f6565b82610531600160ff195f5416175f55565b61058257613492565b61054057005b61054e5f5461ff0019165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989080602081015b0390a1005b6105946101005f5461ff001916175f55565b613492565b303b159150816105ab575b505f61051a565b60ff1660011490505f6105a4565b600160ff8216109150610513565b34610283575f366003190112610283576105df613408565b60025f5160206150b95f395f51905f525d335f9081526101016020526040902065ffffffffffff815460401c161561065957805465ffffffffffff60401b19169055337fc51fdb96728de385ec7859819e3997bc618362ef0dbca0ad051d856866cda3db5f80a260015f5160206150b95f395f51905f525d005b6387bdc6a960e01b5f5260045ffd5b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90602061069d928181520190610668565b90565b346102835760a0366003190112610283576107796040516106c081610a23565b6004356106cc816108c7565b815261076c6106da36611dd3565b6020830190815261076661075e61074f6040608435946106f986612959565b818801958652610707612a31565b9765ffffffffffff60d01b905160d01b16602089015261ffff60f01b81515160f01b16602689015261ffff60f01b60208251015160f01b16602889015251015162ffffff1690565b60e81b602a860152602d850190565b915160ff1690565b906146f6565b506040519182918261068c565b0390f35b34610283575f366003190112610283576020600260ff5f5160206150b95f395f51905f525c1614604051908152f35b34610283576020366003190112610283576004356107c9816102f0565b6108207f000000000000000000000000cb84cf9bfae383b73dc23c5eff792929d714029a6001600160a01b03166108023082141561296f565b5f5160206150d95f395f51905f52546001600160a01b0316146129d0565b61082861396c565b6040516108559161083a602083610a59565b5f8252601f196108495f610ac7565b0136602084013761358a565b005b6109f4565b34610283575f36600319011261028357610886610881600260ff60c95460081c161490565b613712565b61010060c95461ff0019161760c9557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a161085561396c565b65ffffffffffff81160361028357565b359061030c826108c7565b9060608101918051926060835283518091526020608084019401905f5b81811061092c5750505065ffffffffffff60408262ffffff60208395015116602086015201511691015290565b82518652602095860195909201916001016108ff565b3461028357604036600319011261028357610974600435610962816108c7565b6024359061096f826108c7565b6138a2565b6040518091602082016020835281518091526040830190602060408260051b8601019301915f905b8282106109ab57505050500390f35b919360019193955060206109e48192603f198a82030186526040838a516001600160401b038151168452015191818582015201906108e2565b960192019201859493919261099c565b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b0382111761085757604052565b606081019081106001600160401b0382111761085757604052565b60c081019081106001600160401b0382111761085757604052565b90601f801991011681019081106001600160401b0382111761085757604052565b6040519061030c61012083610a59565b6040519061030c61024083610a59565b6040519061030c606083610a59565b6040519061030c60e083610a59565b6040519061030c604083610a59565b6001600160401b03811161085757601f01601f191660200190565b929192610aee82610ac7565b91610afc6040519384610a59565b829481845281830111610283578281602093845f960137010152565b604036600319011261028357600435610b30816102f0565b602435906001600160401b038211610283573660238301121561028357610b64610855923690602481600401359101610ae2565b90610b9e7f000000000000000000000000cb84cf9bfae383b73dc23c5eff792929d714029a6001600160a01b03166108023082141561296f565b610ba661396c565b613652565b34610283575f366003190112610283577f000000000000000000000000cb84cf9bfae383b73dc23c5eff792929d714029a6001600160a01b03163003610c03576040515f5160206150d95f395f51905f528152602090f35b60405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608490fd5b3461028357602036600319011261028357600435610c8a61396c565b65ffffffffffff60fb541660405190633dd0723360e21b825282600483015260248201525f8160448173b2c8e57eb1eb0b686b63f58e53f859bea615677b5af4918215610d8357610d3d61057d927fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d2945f905f5f925f92610d4d575b610d3893945090610d2e610d339265ffffffffffff1665ffffffffffff1960fb54161760fb55565b612db0565b6139c4565b613ac0565b6040519081529081906020820190565b50505050610d38610d2e610d75610d33933d805f833e610d6d8183610a59565b810190612ce6565b909550859450925090610d06565b612da5565b34610283575f366003190112610283576020610dac600260ff60c95460081c161490565b6040519015158152f35b34610283575f3660031901126102835760406101005465ffffffffffff825191818116835260301c166020820152f35b34610283575f366003190112610283575f60a0604051610e0581610a3e565b828152826020820152826040820152826060820152826080820152015260c0610e2c612e43565b60a06040519165ffffffffffff815116835265ffffffffffff602082015116602084015265ffffffffffff604082015116604084015265ffffffffffff606082015116606084015265ffffffffffff6080820151166080840152015160a0820152f35b34610283575f36600319011261028357610ea761396c565b606580546001600160a01b03199081169091556033805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610283575f36600319011261028357606554336001600160a01b0390911603610f215761085533613b46565b60405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608490fd5b34610283576020366003190112610283576004356001600160401b03811161028357604060031982360301126102835760405190610fb582610a08565b80600401356001600160401b038111610283576024610fdc60209260043691860101612f42565b92838552013592610fec84612abd565b0191825260c08101906110af61109261101261100d855151603a0260830190565b612a53565b9260a061108761107561105c61104f61104360208a01611038885165ffffffffffff1690565b60d01b815260060190565b60208781015182520190565b6040860151815260200190565b60608501516001600160a01b031660601b815260140190565b608084015165ffffffffffff16611038565b910151815260200190565b61109d845151614865565b83515161ffff1660f01b815260020190565b905f915b83518051841015611113576001916110ce8561110b93613303565b51805160601b6bffffffffffffffffffffffff19168252602081015160d01b6001600160d01b031916601483015260400151601a820152603a0190565b9201916110b3565b6107798361076c846111258a51151590565b15611132576001906146f6565b5f906146f6565b34610283575f3660031901126102835761116461115e600260ff60c95460081c161490565b15613712565b61020060c95461ff0019161760c9557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a161085561396c565b34610283575f366003190112610283575f5160206150d95f395f51905f52546040516001600160a01b039091168152602090f35b34610283575f366003190112610283576033546040516001600160a01b039091168152602090f35b9181601f84011215610283578235916001600160401b038311610283576020838186019501011161028357565b6040600319820112610283576004356001600160401b038111610283578161125891600401611201565b92909291602435906001600160401b0382116102835761127a91600401611201565b9091565b34610283576112bd6112b86112923661122e565b6112a0959395949294613408565b60025f5160206150b95f395f51905f525d3691610ae2565b613b99565b65ffffffffffff81511680159081156113b1575b50156113a25765ffffffffffff60016113336113509361139a9660fc54906112fe8265ffffffffffff1690565b978891611320603085901c65ffffffffffff169460601c65ffffffffffff1690565b9461132e8985161515612fc7565b613cbd565b93011665ffffffffffff1665ffffffffffff1960fc54161760fc55565b60fc80546bffffffffffff00000000000019164360301b6bffffffffffff00000000000016179055610d3861138b825165ffffffffffff1690565b61139483613f08565b90613a16565b610855614621565b63559895a360e01b5f5260045ffd5b90504211155f6112d1565b346102835760203660031901126102835760206113da600435612ff1565b604051908152f35b602060031982011261028357600435906001600160401b0382116102835761127a91600401611201565b346102835760a06114326112b8611422366113e2565b61142a61304c565b503691610ae2565b60ff604080519265ffffffffffff81511684526114786020820151602086019062ffffff6040809261ffff815116855261ffff6020820151166020860152015116910152565b0151166080820152f35b34610283576020366003190112610283576004356001600160401b038111610283576101206003198236030112610283576114bb610a7a565b906114c8816004016108d7565b82526114d6602482016108d7565b60208301526114e7604482016108d7565b60408301526114f860648201610301565b60608301526084810135608083015261151360a482016108d7565b60a083015260c481013560c083015261152e60e48201612964565b60e0830152610104810135916001600160401b0383116102835761155e610d3d9260046107799536920101613071565b610100820152613f08565b81516001600160a01b031681526102408101929161030c91906102209081906020818101516001600160a01b0316908501526040818101516001600160a01b0316908501526060818101516001600160a01b0316908501526080818101516001600160a01b03169085015260a0818101516001600160401b03169085015260c0818101516001600160401b03169085015260e08181015165ffffffffffff16908501526101008181015165ffffffffffff16908501526101208181015165ffffffffffff169085015261014081015161014085015261165461016082015161016086019060ff169052565b6101808101516101808501526116776101a08201516101a086019061ffff169052565b6101c0818101516001600160401b0316908501526101e0818101516001600160401b0316908501526102008181015161ffff1690850152015160ff16910152565b34610283575f366003190112610283576116d06131d4565b506107796116dc610a8a565b7f000000000000000000000000461461e95de3cc306d5424f554463c162433384e6001600160a01b031681527f000000000000000000000000cfb57e95cbab87bfd167b3eddd5c11e2d1613b226001600160a01b031660208201527f00000000000000000000000053789e39e3310737e8c8ced483032aac25b39ded6001600160a01b031660408201527f000000000000000000000000cbf1639b8809adff74bd59ec292e436107852cc96001600160a01b031660608201527f000000000000000000000000a20182131658295f37c1a1efdbdc89eff97d9c586001600160a01b031660808201526001600160401b037f00000000000000000000000000000000000000000000000000000000000000001660a08201526001600160401b037f00000000000000000000000000000000000000000000000000000000000000001660c082015265ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660e082015265ffffffffffff7f0000000000000000000000000000000000000000000000000000000000001c201661010082015265ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000b4166101208201527f000000000000000000000000000000000000000000000000000000000000006461014082015260ff7f000000000000000000000000000000000000000000000000000000000000004b166101608201527f000000000000000000000000000000000000000000000000000000000000000161018082015261ffff7f0000000000000000000000000000000000000000000000000000000000000000166101a08201526001600160401b037f0000000000000000000000000000000000000000000000000000000000989680166101c08201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000032166101e082015261ffff7f00000000000000000000000000000000000000000000000000000000000001801661020082015260ff7f00000000000000000000000000000000000000000000000000000000000000051661022082015260405191829182611569565b604090600319011261028357600435611a2a816102f0565b9060243561069d8161039f565b3461028357611a4536611a12565b90611a4e613408565b60025f5160206150b95f395f51905f525d6001600160a01b038116156104c057335f90815261010160205260409020611b339190611aeb611acb8254611a9a816001600160401b031690565b6001600160401b03811697886001600160401b038216115f14611c3357508092839265ffffffffffff9060401c1690565b65ffffffffffff811615908115611bfb575b50611bb3575b505033614b73565b936001600160401b0385161480611b8e575b611b78575b50611b0c83614688565b907f000000000000000000000000a20182131658295f37c1a1efdbdc89eff97d9c58614be9565b6040516001600160401b03909116815233907f3362c96009316515fccd3dd29c7036c305ad9e892d83dd5681845ac9edb0c9a89080602081015b0390a2610855614621565b805465ffffffffffff60401b191690555f611b02565b508054611bac9060401c65ffffffffffff165b65ffffffffffff1690565b1515611afd565b611bf491611bc091613ffe565b6001600160401b03807f0000000000000000000000000000000000000000000000000000000000000000169116101561401e565b805f611ae3565b611c2b9150611ba1907f000000000000000000000000000000000000000000000000000000000000000090613fdb565b42105f611add565b92839260401c65ffffffffffff1690565b34610283575f36600319011261028357611c5c613408565b60025f5160206150b95f395f51905f525d335f90815261010160205260409020611c85906133db565b6001600160401b03611c9e82516001600160401b031690565b1615611dac57602081019065ffffffffffff611cc0835165ffffffffffff1690565b16611d9d574265ffffffffffff16909152611d2b90335f90815261010160205260409020815181546020909301516dffffffffffff000000000000000060409190911b166dffffffffffffffffffffffffffff199093166001600160401b0390911617919091179055565b611d60611ba165ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001642614034565b60405165ffffffffffff909116815233907f3bbe41cfdd142e0f9b2224dac18c6efd2a6966e35a9ec23ab57ce63a60b33604908060208101611b6d565b63fb52063b60e01b5f5260045ffd5b634555262b60e01b5f5260045ffd5b62ffffff81160361028357565b359061030c82611dbb565b60609060231901126102835760405190611dec82610a23565b8160243561ffff8116810361028357815260443561ffff81168103610283576020820152604060643591611e1f83611dbb565b0152565b60609060031901126102835760405190611e3c82610a23565b8160043561ffff8116810361028357815260243561ffff81168103610283576020820152604060443591611e1f83611dbb565b606036600319011261028357611f1a6020611e8936611e23565b60015f5260fe602052611ebe7f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b7541515613252565b604051809381926312b2aa9160e31b83527f00000000000000000000000000000000000000000000000000000000000000327f000000000000000000000000000000000000000000000000000000000098968060048501613277565b0381738bbdf7b3d44c1cf6aa64db449e93ad5c0d10e63c5af4908115610d83575f91611f53575b5080611f4957005b6108559033614041565b611f75915060203d602011611f7b575b611f6d8183610a59565b810190613268565b5f611f41565b503d611f63565b34610283575f366003190112610283576040516343c3d71960e01b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000989680811660248301527f0000000000000000000000000000000000000000000000000000000000000032166044820152602081606481738bbdf7b3d44c1cf6aa64db449e93ad5c0d10e63c5af48015610d8357610779915f91612046575b506040516001600160401b0390911681529081906020820190565b612068915060203d60201161206e575b6120608183610a59565b8101906132c8565b5f61202b565b503d612056565b34610283575f366003190112610283576065546040516001600160a01b039091168152602090f35b34610283576120ab3661122e565b926120d16120cc6120bb3361407b565b926120c4612e43565b953691610ae2565b614183565b80516120dd81866142d9565b919365ffffffffffff83169788155f1461265a57612132602080870151935b61210c60a0850195865114613317565b60408801996121258b5161211f89612ff1565b1461332d565b1561264b575b0151151590565b9283156125ff575b83612511575b5f99600188146124bb575b5065ffffffffffff16604082018190529165ffffffffffff4216606083015260c08601968751905f190161217e91613303565b5160400151905261218e90612db0565b8351606080860180516040805165ffffffffffff9586168082529890980185166020890152949093169386019390935292151592840192909252916001600160a01b03909116907f7ca0f1e30099488c4ee24e86a6b2c6802e9add6d530919af7aa17db3bcc1cff190608090a261220482614489565b936040518061221f8782919060206040840193600181520152565b035f5160206150995f395f51905f5291a18251604080516002815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a1602083015160405161228b819282919060206040840193600381520152565b035f5160206150995f395f51905f5291a1516040516122b7819282919060206040840193600481520152565b035f5160206150995f395f51905f5291a15160408051600581526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a16080810151604080516006815265ffffffffffff90921660208301527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b1477491a160a00151604051612361819282919060206040840193600781520152565b035f5160206150995f395f51905f5291a1805161237d906132f1565b516040015160405161239c819282919060206040840193600881520152565b035f5160206150995f395f51905f5291a180516123b8906132f1565b515160408051600981526001600160a01b0390921660208301527f960d4d998d188d9c36e4f362ffd9f6ab7c6eb8e6fb06fed6ecc702f2821168ba91a1516123ff906132f1565b5160209081015160408051600b815265ffffffffffff909216928201929092527f6f0efde8b0c0045e52dacc742e064d057851db770103fca4eca3691f06b147749190a17f000000000000000000000000461461e95de3cc306d5424f554463c162433384e6001600160a01b031690813b15610283575f93612497604051968795869485946314bcf3dd60e01b865260048601613363565b03915afa8015610d83576124a757005b806124b55f61085593610a59565b80610279565b65ffffffffffff919a506124ec611ba160206124de6125089460c08c0151613303565b51015165ffffffffffff1690565b612502611ba1606086015165ffffffffffff1690565b90614477565b4203999061214b565b60808601517f000000000000000000000000cbf1639b8809adff74bd59ec292e436107852cc96001600160a01b03169065ffffffffffff169060a0880151604061256360c08b01515f198d0190613303565b51015161257f612571610a9a565b65ffffffffffff9095168552565b60208401526040830152803b156102835760408051631934171960e31b8152835165ffffffffffff1660048201526020840151602482015292015160448301525f908290606490829084905af18015610d83576125eb575b504265ffffffffffff166080830152612140565b806124b55f6125f993610a59565b5f6125d7565b925065ffffffffffff61261b608083015165ffffffffffff1690565b61ffff7f00000000000000000000000000000000000000000000000000000000000001801601164210159261213a565b6126558789614391565b61212b565b6121326020604061267b60c089015165ffffffffffff5f198a011690613303565b510151936120fc565b90602080835192838152019201905f5b8181106126a15750505090565b825180516001600160a01b0316855260208181015165ffffffffffff16818701526040918201519186019190915260609094019390920191600101612694565b34610283576126fd6120cc6126f5366113e2565b61142a61337f565b604051809160208252610779602061277d60c0845160408488015265ffffffffffff8151166060880152838101516080880152604081015160a088015260018060a01b036060820151168288015265ffffffffffff60808201511660e088015260a0810151610100880152015160e0610120870152610140860190612684565b92015115156040840152565b346102835761279736611a12565b61279f613408565b60025f5160206150b95f395f51905f525d6001600160a01b0382169182156104c057816127ce91610101614634565b6127da61042682614688565b6040516001600160401b0391909116815233907fe5e95641fa87bdfef3ce0d39f0c9a37c200f3bf59f53623b3de21e03ed33e3d290602090a360015f5160206150b95f395f51905f525d005b3461028357602036600319011261028357600435612843816102f0565b61284b61396c565b606580546001600160a01b0319166001600160a01b039283169081179091556033549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227005f80a3005b34610283576020366003190112610283576004356001600160401b0381116102835760e06003198236030112610283576113da6128d96020923690600401612f42565b614489565b604051906128eb82610a08565b5f6020838281520152565b156128fd57565b60405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608490fd5b60ff81160361028357565b359061030c82612959565b1561297657565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b19195b1959d85d1958d85b1b60a21b6064820152608490fd5b156129d757565b60405162461bcd60e51b815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201526b6163746976652070726f787960a01b6064820152608490fd5b60408051909190612a428382610a59565b600e815291601f1901366020840137565b90612a5d82610ac7565b612a6a6040519182610a59565b8281528092612a7b601f1991610ac7565b0190602036910137565b519061030c826108c7565b519061030c826102f0565b519061030c82612959565b6001600160401b0381116108575760051b60200190565b8015150361028357565b519061030c82611dbb565b9080601f83011215610283578151612ae981612aa6565b92612af76040519485610a59565b81845260208085019260051b820101908382116102835760208101925b828410612b2357505050505090565b83516001600160401b0381116102835782016040818703601f1901126102835760405190612b5082610a08565b6020810151612b5e81612abd565b825260408101516001600160401b0381116102835760209101016060818803126102835760405190612b8f82610a23565b80516001600160401b03811161028357810188601f8201121561028357805190612bb882612aa6565b91612bc66040519384610a59565b80835260208084019160051b830101918b831161028357602001905b828210612c255750505091612c11604060209694938796948452612c07878201612ac7565b8785015201612a85565b604082015283820152815201930192612b14565b8151815260209182019101612be2565b9190916101208184031261028357612c4b610a7a565b92612c5582612a85565b8452612c6360208301612a85565b6020850152612c7460408301612a85565b6040850152612c8560608301612a90565b606085015260808201516080850152612ca060a08301612a85565b60a085015260c082015160c0850152612cbb60e08301612a9b565b60e08501526101008201516001600160401b03811161028357612cde9201612ad2565b610100830152565b8082039261012084126102835760c08251612d00816108c7565b94601f19011261028357604051612d1681610a3e565b6020830151612d24816108c7565b81526040830151612d34816108c7565b60208201526060830151612d47816108c7565b60408201526080830151612d5a816108c7565b606082015260a0830151612d6d816108c7565b608082015260c083015160a08201529260e08301516001600160401b0381116102835761010091612d9f918501612c35565b92015190565b6040513d5f823e3d90fd5b805160fc805460208401516040850151606080870151608088015165ffffffffffff60c01b60c09190911b166001600160f01b031990951665ffffffffffff909716969096176bffffffffffff00000000000060309490941b9390931692909217911b65ffffffffffff60601b161760909390931b65ffffffffffff60901b169290921791909117905560a0015160fd55565b60405190612e5082610a3e565b81612e9b65ffffffffffff60fc548181168452818160301c166020850152818160601c16604085015281808260901c1616606085015260c01c16608083019065ffffffffffff169052565b60a060fd54910152565b81601f8201121561028357803590612ebc82612aa6565b92612eca6040519485610a59565b8284526020606081860194028301019181831161028357602001925b828410612ef4575050505090565b606084830312610283576020606091604051612f0f81610a23565b8635612f1a816102f0565b815282870135612f29816108c7565b8382015260408701356040820152815201930192612ee6565b91909160e08184031261028357612f57610aa9565b92612f61826108d7565b84526020820135602085015260408201356040850152612f8360608301610301565b6060850152612f94608083016108d7565b608085015260a082013560a085015260c08201356001600160401b03811161028357612fc09201612ea5565b60c0830152565b15612fce57565b63ba74d80f60e01b5f5260045ffd5b634e487b7160e01b5f52601260045260245ffd5b7f000000000000000000000000000000000000000000000000000000000000006490811561302957065f5260fe60205260405f205490565b612fdd565b6040519061303b82610a23565b5f6040838281528260208201520152565b6040519061305982610a23565b5f60408382815261306861302e565b60208201520152565b9080601f8301121561028357813561308881612aa6565b926130966040519485610a59565b81845260208085019260051b820101908382116102835760208101925b8284106130c257505050505090565b83356001600160401b0381116102835782016040818703601f19011261028357604051906130ef82610a08565b60208101356130fd81612abd565b825260408101356001600160401b038111610283576020910101606081880312610283576040519061312e82610a23565b80356001600160401b03811161028357810188601f820112156102835780359061315782612aa6565b916131656040519384610a59565b80835260208084019160051b830101918b831161028357602001905b8282106131c457505050916131b06040602096949387969484526131a6878201611dc8565b87850152016108d7565b6040820152838201528152019301926130b3565b8135815260209182019101613181565b6131dc610a8a565b905f82525f60208301525f60408301525f60608301525f60808301525f60a08301525f60c08301525f60e08301525f6101008301525f6101208301525f6101408301525f6101608301525f6101808301525f6101a08301525f6101c08301525f6101e08301525f6102008301525f610220830152565b1561325957565b63f37a8b1360e01b5f5260045ffd5b90816020910312610283575190565b6060906001600160401b0361030c94969593968160c084019860ff8552166020840152166040820152019062ffffff6040809261ffff815116855261ffff6020820151166020860152015116910152565b90816020910312610283575161069d8161039f565b634e487b7160e01b5f52603260045260245ffd5b8051156132fe5760200190565b6132dd565b80518210156132fe5760209160051b010190565b1561331e57565b63198070b360e01b5f5260045ffd5b1561333457565b63f904c2fd60e01b5f5260045ffd5b908060209392818452848401375f828201840152601f01601f1916010190565b61069d9492606092825260208201528160408201520191613343565b6040519061338c82610a08565b60405160e08101836001600160401b03821183831017610857575f9260209260405283815283838201528360408201528360608201528360808201528360a0820152606060c082015281520152565b906040516133e881610a08565b91546001600160401b038116835260401c65ffffffffffff166020830152565b600260ff5f5160206150b95f395f51905f525c161461342357565b63dfc60d8560e01b5f5260045ffd5b1561343957565b60405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608490fd5b6134ab60ff5f5460081c166134a681613432565b613432565b6001600160a01b0381166134d457506134c333613b46565b61010060c95461ff0019161760c955565b6134c390613b46565b156134e457565b60405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608490fd5b60809060208152602e60208201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960408201526d6f6e206973206e6f74205555505360901b60608201520190565b906135b67f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b156135c5575061030c906147bd565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f9281613631575b5061360f5760405162461bcd60e51b81528061360b6004820161353b565b0390fd5b61030c9261362c5f5160206150d95f395f51905f525f94146134dd565b6146ff565b61364b91935060203d602011611f7b57611f6d8183610a59565b915f6135ed565b9061367e7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1690565b1561368d575061030c906147bd565b6040516352d1902d60e01b8152906020826004816001600160a01b0387165afa5f92816136f1575b506136d35760405162461bcd60e51b81528061360b6004820161353b565b61030c9261362c5f5160206150d95f395f51905f52600194146134dd565b61370b91935060203d602011611f7b57611f6d8183610a59565b915f6136b5565b1561371957565b63bae6e2a960e01b5f5260045ffd5b6040519061373582610a23565b5f604083606081528260208201520152565b6040519061375482610a08565b815f81526020613762613728565b910152565b60405190613776602083610a59565b5f80835282815b82811061378957505050565b602090613794613747565b8282850101520161377d565b906137aa82612aa6565b6137b76040519182610a59565b82815280926137c8601f1991612aa6565b01905f5b8281106137d857505050565b6020906137e3613747565b828285010152016137cc565b906040516137fc81610a23565b80926040518060208354918281520190835f5260205f20905f5b81811061386357505050600161030c949383613839604095613856950382610a59565b8552015462ffffff8116602085015260181c65ffffffffffff1690565b65ffffffffffff16910152565b8254845260209093019260019283019201613816565b9060405161388681610a08565b6020613762600183956001600160401b038154168552016137ef565b6101005465ffffffffffff8281169493603083901c821693929091168510801561395a575b801561394a575b61393d576138e9929165ffffffffffff809216920316614859565b6138f2816137a0565b925f5b82811061390157505050565b8061392161391c846001940160ff905f5260205260405f2090565b613879565b61392b8288613303565b526139368187613303565b50016138f5565b505050905061069d613767565b5065ffffffffffff8116156138ce565b5065ffffffffffff83168510156138c7565b6033546001600160a01b0316330361398057565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b7f000000000000000000000000000000000000000000000000000000000000006415613029575f805260fe6020527f32796e36004994222362c2f9423d5e208bb848170964890784a8d59ed40f50af55565b7f00000000000000000000000000000000000000000000000000000000000000649081156130295765ffffffffffff16065f5260fe60205260405f2055565b9080602083519182815201916020808360051b8301019401925f915b838310613a8057505050505090565b9091929394602080613ab1600193601f198682030187526040838b51805115158452015191818582015201906108e2565b97019301930191939290613a71565b65ffffffffffff8151167f7c4c4523e17533e451df15762a093e0693a2cd8b279fe54c6cd3777ed577121360018060a01b03606084015116926080810151613b4165ffffffffffff6040840151169261010060ff60e08301511691015190604051948594855260208501526040840152608060608401526080830190613a55565b0390a3565b606580546001600160a01b0319908116909155603380549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b9060ff602d613ba661304c565b93602081015160d01c8552602681015160f01c6020860190815152602882015160f01c6020825101526040602a83015160e81c91510152016001815160f81c915050166040830152565b6040519061012082018281106001600160401b03821117610857576040526060610100835f81525f60208201525f60408201525f838201525f60808201525f60a08201525f60c08201525f60e08201520152565b15613c4b57565b6349517a1d60e11b5f5260045ffd5b15613c6157565b63eaabac9b60e01b5f5260045ffd5b90816020910312610283575161069d816108c7565b6001600160a01b03909116815260406020820181905261069d93910191613343565b15613cae57565b63e92c469f60e01b5f5260045ffd5b9294613d1c90613ce365ffffffffffff613d239497613cda613bf0565b50164311613c44565b5f1965ffffffffffff918803821681019091167f0000000000000000000000000000000000000000000000000000000000000064030190565b1515613c5a565b613d7c613d536020613d4b613d45613d3f604088015160ff1690565b60ff1690565b336148ad565b940151614a44565b613d5b610ab8565b905f8252602082015283515f1981510191613d768383613303565b52613303565b505f92613d8f6105066020850151151590565b613e3c575b50505f19430190613deb613db265ffffffffffff5f19870116612ff1565b915193613dce613dc0610a7a565b65ffffffffffff9097168752565b4265ffffffffffff16602087015265ffffffffffff166040860152565b336060850152608084015265ffffffffffff811660a08401524060c083015260ff7f000000000000000000000000000000000000000000000000000000000000004b1660e083015261010082015290565b604051635600026d60e11b815292935060209183918291613e61913360048501613c85565b03815f7f000000000000000000000000cfb57e95cbab87bfd167b3eddd5c11e2d1613b226001600160a01b03165af1908115610d83575f91613ed9575b5090613ed2613ecd7f000000000000000000000000000000000000000000000000000000000000000033614b2d565b613ca7565b5f80613d94565b613efb915060203d602011613f01575b613ef38183610a59565b810190613c70565b5f613e9e565b503d613ee9565b604051613fc181613fb3610100602083019560208752613f3360408501825165ffffffffffff169052565b602081015165ffffffffffff166060850152604081015165ffffffffffff16608085015260608101516001600160a01b031660a0850152608081015160c085015260a081015165ffffffffffff1660e085015260c08101518483015260e081015160ff166101208501520151610120610140840152610160830190613a55565b03601f198101835282610a59565b51902090565b634e487b7160e01b5f52601160045260245ffd5b9065ffffffffffff8091169116019065ffffffffffff8211613ff957565b613fc7565b906001600160401b03809116911603906001600160401b038211613ff957565b1561402557565b6321f68cc160e21b5f5260045ffd5b91908201809211613ff957565b61030c915a91614c3a565b91908260409103126102835760208251612d9f81612abd565b1561406c57565b63c1a58f1960e01b5f5260045ffd5b7f00000000000000000000000053789e39e3310737e8c8ced483032aac25b39ded6001600160a01b031690811561412e5760408051633326844b60e11b81526001600160a01b0390921660048301529091829060249082905afa8015610d83575f915f916140fd575b50156140f8576140f390614065565b600190565b505f90565b9050614121915060403d604011614127575b6141198183610a59565b81019061404c565b5f6140e4565b503d61410f565b50505f90565b9061413e82612aa6565b61414b6040519182610a59565b828152809261415c601f1991612aa6565b01905f5b82811061416c57505050565b60209061417761302e565b82828501015201614160565b9061ffff6142476142336141cf61421f6142126141fe6141ea6141d96141cf6141be60206141af61337f565b9d01906006825160d01c920190565b91908d519065ffffffffffff169052565b9060208251920190565b9060208c5101529060208251920190565b9060408b510152906014825160601c920190565b919060608a51019060018060a01b03169052565b906006825160d01c920190565b919060808851019065ffffffffffff169052565b9060a086510152906002825160f01c920190565b911661425281614134565b60c0855101525f905b8082106142715750505160f81c15156020830152565b909161427e600191614c7d565b939061428f8260c089510151613303565b52019061425b565b1561429e57565b6363db3a4160e01b5f5260045ffd5b156142b457565b63677c56f160e01b5f5260045ffd5b156142ca57565b63181432e760e11b5f5260045ffd5b909165ffffffffffff60018160408501511601169260c08101515193841561438257614375611ba1836143288465ffffffffffff61432061069d985165ffffffffffff1690565b161115614297565b61435d614356611ba15f198b614347611ba1875165ffffffffffff1690565b0101995165ffffffffffff1690565b88106142ad565b614369848810156142c3565b5165ffffffffffff1690565b900365ffffffffffff1690565b63c2e5347d60e01b5f5260045ffd5b60c081019161441165ffffffffffff60206143b182875195168095613303565b5101511665ffffffffffff808060fc5460901c167f00000000000000000000000000000000000000000000000000000000000000b40116917f0000000000000000000000000000000000000000000000000000000000001c200116614477565b42111561447257606061443c61442e61444b9361030c9651613303565b51516001600160a01b031690565b9201516001600160a01b031690565b7f000000000000000000000000000000000000000000000000000000000000000091614cab565b505050565b9080821115614484575090565b905090565b60c081015180519061455160a06144b56003850260090190604051828193825260010160051b01604052565b602080820152946144db6144d2611ba1835165ffffffffffff1690565b60408801528690565b5060208101516060870152604081015160808701526060810151614522906145199061450d906001600160a01b031681565b6001600160a01b031690565b60a08801528690565b5061454561453c611ba1608084015165ffffffffffff1690565b60c08801528690565b50015160e08501528390565b5060e061010084015261012083018290525f9060095b83831061459f575050505061069d614586826020815160051b91012090565b918051604051828260010160051b011490151060061b52565b600360019161461760406145b38787613303565b5180516145dc906145ce9061450d906001600160a01b031681565b6001860160051b8c01528a90565b506146066145f6611ba1602084015165ffffffffffff1690565b60018689010160051b8c01528a90565b5001516003830160051b8901528790565b5001920191614567565b60015f5160206150b95f395f51905f525d565b6001600160a01b039091165f90815260209190915260409020906001600160401b03808354169116016001600160401b038111613ff957815467ffffffffffffffff19166001600160401b03909116179055565b6001600160401b0316633b9aca00810290808204633b9aca001490151715613ff95790565b6040516323b872dd60e01b60208201526001600160a01b03928316602482015292909116604483015260648083019390935291815261030c916146f1608483610a59565b614da9565b60019181530190565b91614709836147bd565b6001600160a01b0383167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2815115908115916147b5575b5061474c575050565b6147b2915f8060405193614761606086610a59565b602785527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c6020860152660819985a5b195960ca1b6040860152602081519101845af46147ac614fd0565b91614fff565b50565b90505f614743565b803b156147fe5760018060a01b03166bffffffffffffffffffffffff60a01b5f5160206150d95f395f51905f525416175f5160206150d95f395f51905f5255565b60405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608490fd5b81811115614484575090565b61ffff1061486f57565b63161e7a6b60e11b5f5260045ffd5b6040519061488b82610a08565b5f602083606081520152565b1561489e57565b63014b3fdb60e11b5f5260045ffd5b919065ffffffffffff61030c916148c261487e565b94610100546148e86148d98265ffffffffffff1690565b9160301c65ffffffffffff1690565b916149158583850316918286115f146149e757829384915b61490c600184016137a0565b90818d52614e95565b9290947f00000000000000000000000000000000000000000000000000000000000000011191826149dd575b505061499f575b50501660ff7f00000000000000000000000000000000000000000000000000000000000000051661ffff7f000000000000000000000000000000000000000000000000000000000000000016020142116020840152565b6105066149d1916149d6937f000000000000000000000000000000000000000000000000000000000000000091614f92565b614897565b5f80614948565b1190505f80614941565b85938491614900565b156149f757565b63fdac229f60e01b5f5260045ffd5b90614a1082612aa6565b614a1d6040519182610a59565b8281528092612a7b601f1991612aa6565b15614a3557565b637bb2fa2f60e11b5f5260045ffd5b90614a4d613728565b506020820191614a6d61ffff614a65855161ffff1690565b1615156149f0565b614a8b614a86614a7f855161ffff1690565b61ffff1690565b614a06565b915f5b614a9d614a7f865161ffff1690565b811015614aef57614a7f600182614ac5614a9d94614ac0614a7f895161ffff1690565b614034565b49614ad08289613303565b52614ae6614ade8289613303565b511515614a2e565b01915050614a8e565b509250614b056040614b1c92015162ffffff1690565b614b0d610a9a565b92835262ffffff166020830152565b4265ffffffffffff16604082015290565b60018060a01b03165f526101016020526001600160401b0360405f205491166001600160401b03821610159081614b62575090565b65ffffffffffff915060401c161590565b6001600160a01b03165f9081526101016020526040902080549092916001600160401b039182169181168211614bc15750506001600160401b03825416916001600160401b03198154169055565b92614bcf8461030c93613ffe565b6001600160401b03166001600160401b0319825416179055565b60405163a9059cbb60e01b60208201526001600160a01b03909216602483015260448083019390935291815261030c916146f1606483610a59565b15614c2b57565b634c67134d60e11b5f5260045ffd5b919080156144725761030c925f92839260405192614c59602085610a59565b848452614c706001600160a01b0382161515614c24565b60208451940192f1614c24565b614c8561302e565b91815160601c8352601482015160d01c6020840152603a601a8301519201916040840152565b6001600160a01b0381165f908152610101602052604090209092919080546001600160401b039081169084168111614d945750805467ffffffffffffffff1981169091556001600160401b03165b6001600160401b03811615614d8e577faa22f5157944b5fa6846460e159d57ea9c3878e71fda274af372fa2ccf285aa0916001600160401b0382614d4d677fffffffffffffff60609560011c168092613ffe565b9080614d7c575b60408051978416885260208801919091529116908501526001600160a01b03908116941692a3565b614d898185610101614634565b614d54565b50505050565b90614da490614bcf858094613ffe565b614cf9565b90614e039160018060a01b03165f8060405193614dc7604086610a59565b602085527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564602086015260208151910182855af16147ac614fd0565b8051908115918215614e71575b505015614e1957565b60405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608490fd5b9091506020908201829003126102835760200151614e8e81612abd565b5f80614e10565b939190938315614f84575f5f5b858110614f0a575060406020614ed565ffffffffffff969798614ed08896633b9aca00614ee5970290614041565b6132f1565b510151015165ffffffffffff1690565b941601169061030c826101009065ffffffffffff1665ffffffffffff19825416179055565b90600190614f7c614f70614f318565ffffffffffff89160160ff905f5260205260405f2090565b614f39610ab8565b60018152614f488683016137ef565b6020820152614f57878d613303565b52614f62868c613303565b50546001600160401b031690565b6001600160401b031690565b019101614ea2565b5065ffffffffffff93509150565b65ffffffffffff8091169116811461412e575f5260ff60205265ffffffffffff600260405f20015460181c1690811561412e5761ffff160142101590565b3d15614ffa573d90614fe182610ac7565b91614fef6040519384610a59565b82523d5f602084013e565b606090565b919290156150615750815115615013575090565b3b1561501c5790565b60405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606490fd5b8251909150156150745750805190602001fd5b60405162461bcd60e51b81526020600482015290819061360b90602483019061066856fe712de588b76f7fdb47439ab8677a0c8233392168ef0308d402c7b8d72138a080a5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220f86c43e17817ce316cd3d772eaca06b07592db2cfd160e26ed1e615a9f74846a64736f6c634300081e0033
External libraries
LibForcedInclusion : 0x8bBdF7B3D44c1CF6aA64Db449E93aD5C0d10E63c
LibInboxSetup : 0xb2c8E57eb1eb0b686B63f58E53f859bEA615677B