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-05-09T15:50:56.867920Z
Constructor Arguments
0x0000000000000000000000004c7a8b639edf48b2cb254bdb1a1c76558933c20c00000000000000000000000083950e54c2d1659c184ceb43f906c310b27b7542000000000000000000000000a4e7bf2f4f27989aa0a6b7d692edd195048fd2500000000000000000000000004e5099105ab4c73cf227abcdd0d5e1802ae936dc000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af0
Arg [0] (address) : 0x4c7a8b639edf48b2cb254bdb1a1c76558933c20c
Arg [1] (address) : 0x83950e54c2d1659c184ceb43f906c310b27b7542
Arg [2] (address) : 0xa4e7bf2f4f27989aa0a6b7d692edd195048fd250
Arg [3] (address) : 0x4e5099105ab4c73cf227abcdd0d5e1802ae936dc
Arg [4] (address) : 0xf4d761f2e88e7d572aa74feb135b7cdafd727af0
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.
uint48 private constant _RING_BUFFER_SIZE = 10_000_000;
// ---------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------
constructor(
address _proofVerifier,
address _proposerChecker,
address _proverWhitelist,
address _signalService,
address _bondToken
)
// See `MainnetInbox.sol` for details on the configuration.
Inbox(Config({
proofVerifier: _proofVerifier,
proposerChecker: _proposerChecker,
proverWhitelist: _proverWhitelist,
signalService: _signalService,
bondToken: _bondToken,
minBond: 0,
livenessBond: 0,
withdrawalDelay: 1 weeks,
provingWindow: 4 hours,
permissionlessProvingDelay: 5 days,
maxProofSubmissionDelay: 3 minutes,
ringBufferSize: _RING_BUFFER_SIZE,
basefeeSharingPctg: 75,
forcedInclusionDelay: 0 seconds, // Devnet: immediate forced inclusion for faster testing
forcedInclusionFeeInGwei: 1_000_000,
forcedInclusionFeeDoubleThreshold: 50,
permissionlessInclusionMultiplier: 160
}))
{ }
// ---------------------------------------------------------------
// Internal Functions
// ---------------------------------------------------------------
function _storeReentryLock(uint8 _reentry) internal override {
LibFasterReentryLock.storeReentryLock(_reentry);
}
function _loadReentryLock() internal view override returns (uint8) {
return LibFasterReentryLock.loadReentryLock();
}
}
contracts/shared/common/IResolver.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IResolver
/// @notice This contract acts as a bridge for name-to-address resolution.
/// @custom:security-contact security@taiko.xyz
interface IResolver {
error RESOLVED_TO_ZERO_ADDRESS();
/// @notice Resolves a name to its address deployed on a specified chain.
/// @param _chainId The chainId of interest.
/// @param _name Name whose address is to be resolved.
/// @param _allowZeroAddress If set to true, does not throw if the resolved
/// address is `address(0)`.
/// @return Address associated with the given name on the specified
/// chain.
function resolve(
uint256 _chainId,
bytes32 _name,
bool _allowZeroAddress
)
external
view
returns (address);
}
node_modules/@openzeppelin/contracts/utils/StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}
contracts/layer1/core/iface/IForcedInclusionStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { LibBlobs } from "../libs/LibBlobs.sol";
/// @title IForcedInclusionStore
/// @custom:security-contact security@taiko.xyz
interface IForcedInclusionStore {
/// @notice Represents a forced inclusion that will be stored onchain.
struct ForcedInclusion {
/// @notice The fee in Gwei that was paid to submit the forced inclusion.
uint64 feeInGwei;
/// @notice The proposal's blob slice.
LibBlobs.BlobSlice blobSlice;
}
/// @dev Event emitted when a forced inclusion is stored.
event ForcedInclusionSaved(ForcedInclusion forcedInclusion);
/// @notice Saves a forced inclusion request
/// A priority fee must be paid to the contract
/// @dev Only one blob reference can be saved per forced inclusion
/// @param _blobReference The blob locator that contains the transaction data
function saveForcedInclusion(LibBlobs.BlobReference memory _blobReference) external payable;
/// @notice Returns the current dynamic forced inclusion fee based on queue size
/// The fee scales linearly with queue size using the formula:
/// fee = baseFee × (1 + numPending / threshold)
/// Examples with threshold = 100 and baseFee = 0.01 ETH:
/// - 0 pending: fee = 0.01 × (1 + 0/100) = 0.01 ETH (1× base)
/// - 50 pending: fee = 0.01 × (1 + 50/100) = 0.015 ETH (1.5× base)
/// - 100 pending: fee = 0.01 × (1 + 100/100) = 0.02 ETH (2× base, DOUBLED)
/// - 150 pending: fee = 0.01 × (1 + 150/100) = 0.025 ETH (2.5× base)
/// - 200 pending: fee = 0.01 × (1 + 200/100) = 0.03 ETH (3× base, TRIPLED)
/// @return feeInGwei_ The current fee in Gwei
function getCurrentForcedInclusionFee() external view returns (uint64 feeInGwei_);
/// @notice Returns forced inclusions stored starting from a given index.
/// @dev Returns an empty array if `_start` is outside the valid range [head, tail) or if
/// `_maxCount` is zero. Otherwise returns actual stored entries from the queue.
/// @param _start The queue index to start reading from (must be in range [head, tail)).
/// @param _maxCount Maximum number of inclusions to return. Passing zero returns an empty
/// array.
/// @return inclusions_ Forced inclusions from the queue starting at `_start`. The actual length
/// will be `min(_maxCount, tail - _start)`, or zero if `_start` is out of range.
function getForcedInclusions(
uint48 _start,
uint48 _maxCount
)
external
view
returns (ForcedInclusion[] memory inclusions_);
/// @notice Returns the queue pointers for the forced inclusion store.
/// @return head_ Index of the oldest forced inclusion in the queue.
/// @return tail_ Index of the next free slot in the queue.
function getForcedInclusionState() external view returns (uint48 head_, uint48 tail_);
}
node_modules/@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
contracts/layer1/verifiers/IProofVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProofVerifier
/// @notice Interface for verifying validity proofs for state transitions
/// @custom:security-contact security@taiko.xyz
interface IProofVerifier {
/// @notice Verifies a validity proof for a state transition
/// @dev This function must revert if the proof is invalid
/// @param _proposalAge The age in seconds of the proposal being proven. Only set for
/// single-proposal proofs (calculated as block.timestamp - proposal.timestamp).
/// For multi-proposal batches, this is always 0, meaning "not applicable".
/// Verifiers should interpret _proposalAge == 0 as "not applicable" rather than
/// "instant proof". This parameter enables age-based verification logic, such as
/// detecting and handling prover-killer proposals differently.
/// @param _commitmentHash Hash of the last proposal hash and commitment data
/// @param _proof The proof data
function verifyProof(
uint256 _proposalAge,
bytes32 _commitmentHash,
bytes calldata _proof
)
external
view;
}
contracts/layer1/core/libs/LibBlobs.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.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_);
}
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.
uint48 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.permissionlessProvingDelay > _config.provingWindow,
PermissionlessProvingDelayTooSmall()
);
require(_config.ringBufferSize >= MIN_RING_BUFFER_SIZE, RingBufferSizeTooSmall());
require(_config.basefeeSharingPctg <= 100, BasefeeSharingPctgTooLarge());
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 PermissionlessProvingDelayTooSmall();
error PermissionlessInclusionMultiplierTooSmall();
error ProofVerifierZero();
error ProposerCheckerZero();
error ProvingWindowZero();
error RingBufferSizeTooSmall();
error SignalServiceZero();
}
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/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_);
}
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/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 The delay after which proving becomes permissionless when whitelist is enabled
/// @dev Must be greater than provingWindow
uint48 permissionlessProvingDelay;
/// @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
uint48 ringBufferSize;
/// @notice The percentage of basefee paid to coinbase
uint8 basefeeSharingPctg;
/// @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 forced inclusion fee doubles
uint64 forcedInclusionFeeDoubleThreshold;
/// @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 L1 block number where the most recent proposal was made.
uint48 lastProposalBlockId;
/// @notice The ID of the last proven (finalized) proposal.
uint48 lastFinalizedProposalId;
/// @notice The timestamp when the last proposal was proven (finalized).
uint48 lastFinalizedTimestamp;
/// @notice The timestamp when the last checkpoint was saved.
/// @dev This is 0 until the first successful `prove` call saves a checkpoint.
uint48 lastCheckpointTimestamp;
/// @notice The block hash of the last proven (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 the proposer does not
/// wish to include any queued inclusions.
uint16 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 The 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 block hash of the parent of the first proposal.
/// @dev Used to verify the proof range links to `CoreState.lastFinalizedBlockHash`.
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.
struct ProveInput {
/// @notice The commitment data that the proof verifies.
Commitment commitment;
}
/// @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;
}
// ---------------------------------------------------------------
// 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
event Proved(
uint48 firstProposalId,
uint48 firstNewProposalId,
uint48 lastProposalId,
address indexed actualProver
);
// ---------------------------------------------------------------
// 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 syncing
/// @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);
// ---------------------------------------------------------------
// Constants
// ---------------------------------------------------------------
/// @notice Maximum number of forced inclusions processed per proposal.
/// @dev Must be < 12 to avoid derived block timestamps drifting into the future when proposals
/// happen every L1 slot (Derivation enforces 1s block times).
uint256 internal constant MAX_FORCED_INCLUSIONS_PER_PROPOSAL = 10;
// ---------------------------------------------------------------
// 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 The delay after which proving becomes permissionless when whitelist is enabled.
uint48 internal immutable _permissionlessProvingDelay;
/// @notice Maximum delay allowed between sequential proofs to remain on time.
uint48 internal immutable _maxProofSubmissionDelay;
/// @notice The ring buffer size for storing proposal hashes.
uint48 internal immutable _ringBufferSize;
/// @notice The percentage of basefee paid to coinbase.
uint8 internal immutable _basefeeSharingPctg;
/// @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 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;
_permissionlessProvingDelay = _config.permissionlessProvingDelay;
_maxProofSubmissionDelay = _config.maxProofSubmissionDelay;
_ringBufferSize = _config.ringBufferSize;
_basefeeSharingPctg = _config.basefeeSharingPctg;
_forcedInclusionDelay = _config.forcedInclusionDelay;
_forcedInclusionFeeInGwei = _config.forcedInclusionFeeInGwei;
_forcedInclusionFeeDoubleThreshold = _config.forcedInclusionFeeDoubleThreshold;
_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. Processes up to `min(input.numForcedInclusions, MAX_FORCED_INCLUSIONS_PER_PROPOSAL)`
/// forced inclusions. If forced inclusions are due, the proposer must request at least
/// `min(numDue, MAX_FORCED_INCLUSIONS_PER_PROPOSAL)` forced inclusions.
/// 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 When the prover whitelist is enabled, only whitelisted
/// provers may prove until a proposal becomes older than `permissionlessProvingDelay`,
/// after which proving becomes permissionless for that proposal.
/// @dev The proof covers a contiguous range of proposals. The input contains an array of
/// Transition structs, each with the proposal metadata and end block 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 nonReentrant {
unchecked {
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);
uint256 proposalAge = block.timestamp - commitment.transitions[offset].timestamp;
bool isWhitelistEnabled = _checkProver(msg.sender, proposalAge);
// ---------------------------------------------------------
// 2. Verify parent block-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
// -----------------------------------------------------------------------------
_signalService.saveCheckpoint(
ICheckpointStore.Checkpoint({
blockNumber: commitment.endBlockNumber,
stateRoot: commitment.endStateRoot,
blockHash: commitment.transitions[numProposals - 1].blockHash
})
);
state.lastCheckpointTimestamp = uint48(block.timestamp);
// ---------------------------------------------------------
// 5. Update core state and emit event
// ---------------------------------------------------------
state.lastFinalizedProposalId = uint48(lastProposalId);
state.lastFinalizedTimestamp = uint48(block.timestamp);
state.lastFinalizedBlockHash = commitment.transitions[numProposals - 1].blockHash;
_coreState = state;
emit Proved(
commitment.firstProposalId,
commitment.firstProposalId + offset,
uint48(lastProposalId),
commitment.actualProver
);
// ---------------------------------------------------------
// 6. Verify the proof
// ---------------------------------------------------------
// For multi-proposal batches (more than 1 unfinalized proposal), pass 0 to verifier.
// Single-proposal proofs pass actual age for age-based verification logic.
_proofVerifier.verifyProof(
numProposals - offset == 1 ? proposalAge : 0,
LibHashOptimized.hashCommitment(commitment),
_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,
permissionlessProvingDelay: _permissionlessProvingDelay,
maxProofSubmissionDelay: _maxProofSubmissionDelay,
ringBufferSize: _ringBufferSize,
basefeeSharingPctg: _basefeeSharingPctg,
forcedInclusionDelay: _forcedInclusionDelay,
forcedInclusionFeeInGwei: _forcedInclusionFeeInGwei,
forcedInclusionFeeDoubleThreshold: _forcedInclusionFeeDoubleThreshold,
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(
_ringBufferSize > _nextProposalId - _lastFinalizedProposalId, 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);
if (_minBond > 0) {
// Only if thre is a minimum bond set, execute this check
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 dueToProcess;
uint256 maxToInspect = available.min(MAX_FORCED_INCLUSIONS_PER_PROPOSAL);
for (uint256 i; i < maxToInspect; ++i) {
IForcedInclusionStore.ForcedInclusion storage inclusion = $.queue[head + i];
uint256 timestamp = inclusion.blobSlice.timestamp;
if (timestamp == 0 || block.timestamp < timestamp + uint256(_forcedInclusionDelay))
{
break;
}
++dueToProcess;
}
require(
_numForcedInclusionsRequested >= dueToProcess, UnprocessedForcedInclusionIsDue()
);
uint256 toProcess = _numForcedInclusionsRequested.min(available)
.min(MAX_FORCED_INCLUSIONS_PER_PROPOSAL);
result_.sources = new DerivationSource[](toProcess + 1);
uint48 oldestTimestamp;
(oldestTimestamp, head) = _dequeueAndProcessForcedInclusions(
$, _feeRecipient, result_.sources, head, toProcess
);
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 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. When whitelist is enabled, proving
/// becomes permissionless once a proposal is older than the permissionless delay.
/// @param _addr The address of the caller to check.
/// @param _proposalAge The age in seconds since the proposal became available for proving.
/// @return whitelistEnabled_ True if whitelist is enabled (proverCount > 0), false otherwise.
function _checkProver(
address _addr,
uint256 _proposalAge
)
private
view
returns (bool whitelistEnabled_)
{
if (address(_proverWhitelist) == address(0)) return false;
(bool isWhitelisted, uint256 proverCount) = _proverWhitelist.isProverWhitelisted(_addr);
if (proverCount == 0) return false;
if (!isWhitelisted) {
require(_proposalAge > uint256(_permissionlessProvingDelay), 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 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;
}
contracts/layer1/core/iface/IProverWhitelist.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProverWhitelist
/// @notice Interface for checking if an address is authorized to prove blocks
/// @custom:security-contact security@taiko.xyz
interface IProverWhitelist {
/// @notice Checks if an address is a whitelisted prover
/// @param _prover The address to check
/// @return isWhitelisted_ True if the address is whitelisted, false otherwise
/// @return proverCount_ The total number of whitelisted provers
function isProverWhitelisted(address _prover)
external
view
returns (bool isWhitelisted_, uint256 proverCount_);
}
contracts/shared/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/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(15);
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.packUint16(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.unpackUint16(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]);
}
}
/// @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);
}
}
// ---------------------------------------------------------------
// 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
// Total fixed: 130 bytes
size_ = 130 + (_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 referenced block.
bytes32 blockHash;
/// @notice The state root for the referenced block.
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();
}
node_modules/@openzeppelin/contracts/interfaces/IERC1967.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}
node_modules/@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
contracts/shared/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());
}
}
Compiler Settings
{"viaIR":false,"remappings":["openzeppelin/=node_modules/@openzeppelin/","@openzeppelin/=node_modules/@openzeppelin/","@openzeppelin-upgrades/contracts/=node_modules/@openzeppelin/contracts-upgradeable/","@risc0/contracts/=node_modules/risc0-ethereum/contracts/src/","@solady/=node_modules/solady/","solady/src/=node_modules/solady/src/","solady/utils/=node_modules/solady/src/utils/","@optimism/=node_modules/optimism/","@sp1-contracts/=node_modules/sp1-contracts/contracts/","forge-std/=node_modules/forge-std/","@p256-verifier/contracts/=node_modules/p256-verifier/src/","@eth-fabric/urc/=node_modules/urc/src/","ds-test/=node_modules/ds-test/","src/=contracts/","test/=test/","script/=script/","optimism/=node_modules/optimism/","p256-verifier/=node_modules/p256-verifier/","risc0-ethereum/=node_modules/risc0-ethereum/","sp1-contracts/=node_modules/sp1-contracts/","urc/=node_modules/urc/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{},"evmVersion":"prague"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_proofVerifier","internalType":"address"},{"type":"address","name":"_proposerChecker","internalType":"address"},{"type":"address","name":"_proverWhitelist","internalType":"address"},{"type":"address","name":"_signalService","internalType":"address"},{"type":"address","name":"_bondToken","internalType":"address"}]},{"type":"error","name":"ACCESS_DENIED","inputs":[]},{"type":"error","name":"ActivationRequired","inputs":[]},{"type":"error","name":"BlobNotFound","inputs":[]},{"type":"error","name":"CannotProposeInCurrentBlock","inputs":[]},{"type":"error","name":"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":"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}],"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":"uint16","name":"numForcedInclusions","internalType":"uint16"}]}],"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"}]}]}]}],"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":"uint16","name":"numForcedInclusions","internalType":"uint16"}]}]},{"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":"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":"permissionlessProvingDelay","internalType":"uint48"},{"type":"uint48","name":"maxProofSubmissionDelay","internalType":"uint48"},{"type":"uint48","name":"ringBufferSize","internalType":"uint48"},{"type":"uint8","name":"basefeeSharingPctg","internalType":"uint8"},{"type":"uint16","name":"forcedInclusionDelay","internalType":"uint16"},{"type":"uint64","name":"forcedInclusionFeeInGwei","internalType":"uint64"},{"type":"uint64","name":"forcedInclusionFeeDoubleThreshold","internalType":"uint64"},{"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
0x6102e060405230608052348015610014575f5ffd5b50604051615d43380380615d4383398101604081905261003391610301565b60408051610220810182526001600160a01b038088168252868116602083015285811692820192909252838216606082015290821660808201525f60a080830182905260c0830182905262093a8060e08401526138406101008401526206978061012084015260b461014084015262989680610160840152604b6101808401526101a0830191909152620f42406101c083015260326101e08301526102008201526100dc61022a565b6040516348ed17ff60e11b815273aad95c58d4b8ceacdb6717413309e764a28fb557906391da2ffe90610113908490600401610362565b5f6040518083038186803b158015610129575f5ffd5b505af415801561013b573d5f5f3e3d5ffd5b505082516001600160a01b0390811660c09081526020850151821660e09081526040860151831661010090815260608701518416610120908152608088015190941661014090815260a08801516001600160401b039081166101609081529489015181166101809081529389015165ffffffffffff9081166101a0908152938a015181166101c0908152968a015181166101e0908152928a01518116610200908152958a015116610220529288015160ff908116610240529188015161ffff16610260529387015182166102805292860151166102a052909301519092166102c0525061052695505050505050565b5f54610100900460ff16156102955760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116146102e4575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146102fc575f5ffd5b919050565b5f5f5f5f5f60a08688031215610315575f5ffd5b61031e866102e6565b945061032c602087016102e6565b935061033a604087016102e6565b9250610348606087016102e6565b9150610356608087016102e6565b90509295509295909350565b81516001600160a01b031681526102208101602083015161038e60208401826001600160a01b03169052565b5060408301516103a960408401826001600160a01b03169052565b5060608301516103c460608401826001600160a01b03169052565b5060808301516103df60808401826001600160a01b03169052565b5060a08301516103fa60a08401826001600160401b03169052565b5060c083015161041560c08401826001600160401b03169052565b5060e083015161042f60e084018265ffffffffffff169052565b5061010083015161044b61010084018265ffffffffffff169052565b5061012083015161046761012084018265ffffffffffff169052565b5061014083015161048361014084018265ffffffffffff169052565b5061016083015161049f61016084018265ffffffffffff169052565b506101808301516104b661018084018260ff169052565b506101a08301516104ce6101a084018261ffff169052565b506101c08301516104eb6101c08401826001600160401b03169052565b506101e08301516105086101e08401826001600160401b03169052565b5061020083015161051f61020084018260ff169052565b5092915050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516156746106cf5f395f8181610a48015261377101525f8181610a1901528181611676015261173c01525f81816109ea01528181611654015261171401525f81816109c001528181613657015261379501525f8181610997015261297601525f8181610969015281816114330152818161250b015261274801525f818161093b015261314b01525f818161090d01526130f401525f81816108df015261318c01525f81816108b10152818161156901526115b301525f8181610882015261323301525f8181610853015281816115480152818161288c01526128ba01525f818161082401528181610c71015281816115240152611d3f01525f81816107f5015261197201525f81816107c60152818161301a015261307001525f8181610797015261280701525f81816107680152611bf801525f61026901525f8181610ded01528181610e2d01528181610f1f01528181610f5f0152610fd601526156745ff3fe60806040526004361061021d575f3560e01c80638456cb591161011e578063d6dad060116100a8578063ea1917431161006d578063ea19174314610b2d578063edbacd4414610b4c578063efba83c914610b78578063f2fde38b14610b97578063f954ab9214610bb6575f5ffd5b8063d6dad06014610a9e578063dbaf214514610abd578063df596d9e14610ad1578063e305333514610ae4578063e30c397814610b10575f5ffd5b8063a834725a116100ee578063a834725a14610659578063afb63ad414610678578063b28e824e146106a4578063c3f909d4146106c3578063c595459714610a7f575f5ffd5b80638456cb59146105f55780638abf6077146106095780638da5cb5b1461061d5780639791e6441461063a575f5ffd5b80633f4ba83a116101aa5780635c975abb1161016f5780635c975abb146104645780635ccc1718146104845780636aa6a01a146104ba578063715018a6146105cd57806379ba5097146105e1575f5ffd5b80633f4ba83a146103d057806340df9866146103e45780634f1ef2861461041057806352d1902d1461042357806359db6e8514610445575f5ffd5b806313765838116101f0578063137658381461031857806319ab453c1461033957806322611280146103585780633075db561461036c5780633659cfe6146103b1575f5ffd5b80630423c7de1461022157806304f3bcec1461025b5780630d8912f3146102a15780631275a673146102ec575b5f5ffd5b34801561022c575f5ffd5b5060fb5461023f9065ffffffffffff1681565b60405165ffffffffffff90911681526020015b60405180910390f35b348015610266575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610252565b3480156102ac575f5ffd5b506102c06102bb36600461407b565b610bd5565b6040805182516001600160401b0316815260209283015165ffffffffffff169281019290925201610252565b3480156102f7575f5ffd5b5061030b610306366004614096565b610c3e565b60405161025291906140dd565b348015610323575f5ffd5b50610337610332366004614103565b610c57565b005b348015610344575f5ffd5b5061033761035336600461407b565b610ca7565b348015610363575f5ffd5b50610337610db9565b348015610377575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b6040519015158152602001610252565b3480156103bc575f5ffd5b506103376103cb36600461407b565b610de3565b3480156103db575f5ffd5b50610337610ea7565b3480156103ef575f5ffd5b506104036103fe36600461413c565b610f00565b60405161025291906141e1565b61033761041e366004614359565b610f15565b34801561042e575f5ffd5b50610437610fca565b604051908152602001610252565b348015610450575f5ffd5b5061033761045f3660046143fe565b61107b565b34801561046f575f5ffd5b506103a160c954610100900460ff1660021490565b34801561048f575f5ffd5b50610100546040805165ffffffffffff8084168252600160301b909304909216602083015201610252565b3480156104c5575f5ffd5b5061055a6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260fc5465ffffffffffff8082168352600160301b820481166020840152600160601b8204811693830193909352600160901b810483166060830152600160c01b9004909116608082015260fd5460a082015290565b60405161025291905f60c08201905065ffffffffffff835116825265ffffffffffff602084015116602083015265ffffffffffff604084015116604083015265ffffffffffff606084015116606083015265ffffffffffff608084015116608083015260a083015160a083015292915050565b3480156105d8575f5ffd5b50610337611227565b3480156105ec575f5ffd5b50610337611238565b348015610600575f5ffd5b506103376112af565b348015610614575f5ffd5b50610289611304565b348015610628575f5ffd5b506033546001600160a01b0316610289565b348015610645575f5ffd5b50610337610654366004614459565b611312565b348015610664575f5ffd5b506104376106733660046143fe565b611423565b348015610683575f5ffd5b506106976106923660046144c3565b61146e565b6040516102529190614501565b3480156106af575f5ffd5b506104376106be36600461455d565b6114e5565b3480156106ce575f5ffd5b50610a7260408051610220810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091526040518061022001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000060ff1681526020017f000000000000000000000000000000000000000000000000000000000000000061ffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f000000000000000000000000000000000000000000000000000000000000000060ff16815250905090565b6040516102529190614594565b348015610a8a575f5ffd5b5061030b610a99366004614758565b6114f7565b348015610aa9575f5ffd5b50610337610ab836600461478e565b61150a565b348015610ac8575f5ffd5b50610337611598565b610337610adf366004614835565b6115d7565b348015610aef575f5ffd5b50610af86116f6565b6040516001600160401b039091168152602001610252565b348015610b1b575f5ffd5b506065546001600160a01b0316610289565b348015610b38575f5ffd5b50610337610b47366004614459565b6117c1565b348015610b57575f5ffd5b50610b6b610b663660046144c3565b611ca8565b60405161025291906148b3565b348015610b83575f5ffd5b50610337610b9236600461478e565b611d25565b348015610ba2575f5ffd5b50610337610bb136600461407b565b611d71565b348015610bc1575f5ffd5b50610437610bd036600461492e565b611de2565b6040805180820182525f80825260208083018290528351808501855282815281018290526001600160a01b03851682526101018152908390208351808501909452546001600160401b0381168452600160401b900465ffffffffffff1690830152905b92915050565b6060610c38610c5236849003840184614964565b611df4565b610c5f611e5d565b610c696002611ea2565b610c9a6101017f00000000000000000000000000000000000000000000000000000000000000003380856001611eab565b610ca46001611ea2565b50565b5f54610100900460ff1615808015610cc557505f54600160ff909116105b80610cde5750303b158015610cde57505f5460ff166001145b610d465760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015610d67575f805461ff0019166101001790555b610d7082611fb0565b8015610db5575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610dc1611e5d565b610dcb6002611ea2565b610dd76101013361200e565b610de16001611ea2565b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610e2b5760405162461bcd60e51b8152600401610d3d906149b5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610e5d6120a0565b6001600160a01b031614610e835760405162461bcd60e51b8152600401610d3d90614a01565b610e8c816120bb565b604080515f80825260208201909252610ca4918391906120c3565b610eaf61222d565b610ec360c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a1610de1335f61225e565b6060610f0e60ff8484612266565b9392505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610f5d5760405162461bcd60e51b8152600401610d3d906149b5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610f8f6120a0565b6001600160a01b031614610fb55760405162461bcd60e51b8152600401610d3d90614a01565b610fbe826120bb565b610db5828260016120c3565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146110695760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610d3d565b505f5160206155f85f395f51905f5290565b6110836124a8565b60fb54604051633dd0723360e21b81526004810183905265ffffffffffff90911660248201525f9081908190819073aad95c58d4b8ceacdb6717413309e764a28fb5579063f741c8cc906044015f60405180830381865af41580156110ea573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526111119190810190614d06565b60fb805465ffffffffffff191665ffffffffffff86811691909117909155835160fc805460208701516040880151606089015160808a01519587166bffffffffffffffffffffffff1990941693909317600160301b92871692909202919091176bffffffffffffffffffffffff60601b1916600160601b9186169190910265ffffffffffff60901b191617600160901b918516919091021765ffffffffffff60c01b1916600160c01b929093169190910291909117905560a083015160fd55929650909450925090506111e45f82612502565b6111ed8261254c565b6040518581527fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d29060200160405180910390a15050505050565b61122f6124a8565b610de15f6125b7565b60655433906001600160a01b031681146112a65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610d3d565b610ca4816125b7565b6112b76125d0565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a1610de133600161225e565b5f61130d6120a0565b905090565b61131a611e5d565b6113246002611ea2565b5f61136383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260292505050565b905061136e8161268d565b60fc5465ffffffffffff80821691600160301b8104821691600160601b90910416826113ad5760405163ba74d80f60e01b815260040160405180910390fd5b5f6113bc858a8a8787876126c9565b60fc80544365ffffffffffff908116600160301b026bffffffffffffffffffffffff19909216600189019190911617179055805190915061140590611400836129af565b612502565b61140e8161254c565b505050505061141d6001611ea2565b50505050565b5f60fe8161145965ffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001685614df5565b81526020019081526020015f20549050919050565b6114a760408051606080820183525f80835283519182018452808252602082810182905293820152909182019081525f60209091015290565b610f0e83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260292505050565b5f610c386114f283614f93565b6129af565b6060610c386115058361517a565b6129de565b611512611e5d565b61151c6002611ea2565b61158d6101017f00000000000000000000000000000000000000000000000000000000000000003385857f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612ae9565b50610db56001611ea2565b6115a0611e5d565b6115aa6002611ea2565b610dd7610101337f0000000000000000000000000000000000000000000000000000000000000000612c91565b60015f5260fe6020527f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b754806116205760405163f37a8b1360e01b815260040160405180910390fd5b6040516312b2aa9160e31b81525f90735912bae0b1f53f15c2cba5f9ab3718ddda2a6046906395955488906116a09060ff907f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009089906004016151d9565b602060405180830381865af41580156116bb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116df9190615228565b905080156116f1576116f13382612dcd565b505050565b6040516343c3d71960e01b815260ff60048201526001600160401b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f00000000000000000000000000000000000000000000000000000000000000001660448201525f90735912bae0b1f53f15c2cba5f9ab3718ddda2a6046906343c3d71990606401602060405180830381865af415801561179d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061130d919061523f565b6117c9611e5d565b6117d36002611ea2565b6040805160c08101825260fc5465ffffffffffff8082168352600160301b82048116602080850191909152600160601b8304821684860152600160901b830482166060850152600160c01b90920416608083015260fd5460a08301528251601f870182900482028101820190935285835290915f9161186c919088908890819084018382808284375f92019190915250612dd892505050565b80519091505f808061187e8685612f46565b9250925092505f8460c001518265ffffffffffff16815181106118a3576118a361525a565b60200260200101516020015165ffffffffffff16420390505f6118c63383613017565b90505f65ffffffffffff841615611909578660c001516001850365ffffffffffff16815181106118f8576118f861525a565b60200260200101516040015161190f565b86602001515b9050808960a00151146119355760405163198070b360e01b815260040160405180910390fd5b61193e85611423565b8760400151146119615760405163f904c2fd60e01b815260040160405180910390fd5b81611970576119708785613145565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c9a0b8c860405180606001604052808a6080015165ffffffffffff1681526020018a60c0015160018b03815181106119d5576119d561525a565b60200260200101516040015181526020018a60a001518152506040518263ffffffff1660e01b8152600401611a2e9190815165ffffffffffff168152602080830151908201526040918201519181019190915260600190565b5f604051808303815f87803b158015611a45575f5ffd5b505af1158015611a57573d5f5f3e3d5ffd5b50505065ffffffffffff42811660808c0181905290871660408c015260608b01525060c087015180515f198801908110611a9357611a9361525a565b6020026020010151604001518960a00181815250508860fc5f820151815f015f6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506020820151815f0160066101000a81548165ffffffffffff021916908365ffffffffffff1602179055506040820151815f01600c6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506060820151815f0160126101000a81548165ffffffffffff021916908365ffffffffffff1602179055506080820151815f0160186101000a81548165ffffffffffff021916908365ffffffffffff16021790555060a0820151816001015590505086606001516001600160a01b03167fa274dcaff3629ec7d69d144038e97732516ff306fcbf8a2bc9423d106779a2f0885f0151868a5f01510188604051611bee9392919065ffffffffffff93841681529183166020830152909116604082015260600190565b60405180910390a27f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166314bcf3dd8565ffffffffffff168803600114611c3d575f611c3f565b845b611c488a613257565b8e8e6040518563ffffffff1660e01b8152600401611c699493929190615296565b5f6040518083038186803b158015611c7f575f5ffd5b505afa158015611c91573d5f5f3e3d5ffd5b5050505050505050505050505061141d6001611ea2565b60408051610100810182525f6020820181815292820181905260608083018290526080830182905260a0830182905260c083019190915260e0820152908152610f0e83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612dd892505050565b611d2d611e5d565b611d376002611ea2565b611d676101017f00000000000000000000000000000000000000000000000000000000000000003385855f611eab565b610db56001611ea2565b611d796124a8565b606580546001600160a01b0383166001600160a01b03199091168117909155611daa6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f610c38611def836152b5565b613257565b60408051600f8082528183019092526060916020820181803683375050835160d01b60208084019190915284810180515160f090811b6026860152815190920151821b60288501525160409081015160e81b602a8501529094015190931b602d82015292915050565b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff1603610de15760405163dfc60d8560e01b815260040160405180910390fd5b610ca481613396565b6001600160a01b038316611ed25760405163e6c4247b60e01b815260040160405180910390fd5b611edd8684846133bc565b808015611f0f57506001600160a01b0383165f90815260208790526040902054600160401b900465ffffffffffff1615155b15611f3c576001600160a01b0383165f908152602087905260409020805465ffffffffffff60401b191690555b611f5c8430611f4a8561340a565b6001600160a01b038916929190613422565b6040516001600160401b03831681526001600160a01b0380851691908616907fe5e95641fa87bdfef3ce0d39f0c9a37c200f3bf59f53623b3de21e03ed33e3d29060200160405180910390a3505050505050565b5f54610100900460ff16611fd65760405162461bcd60e51b8152600401610d3d906152c0565b611fde61348d565b611ffc6001600160a01b03821615611ff657816125b7565b336125b7565b5060c9805461ff001916610100179055565b6001600160a01b0381165f90815260208390526040812080549091600160401b90910465ffffffffffff169003612058576040516387bdc6a960e01b815260040160405180910390fd5b805465ffffffffffff60401b191681556040516001600160a01b038316907fc51fdb96728de385ec7859819e3997bc618362ef0dbca0ad051d856866cda3db905f90a2505050565b5f5160206155f85f395f51905f52546001600160a01b031690565b610ca46124a8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156120f6576116f1836134b3565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612150575060408051601f3d908101601f1916820190925261214d91810190615228565b60015b6121b35760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610d3d565b5f5160206155f85f395f51905f5281146122215760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610d3d565b506116f183838361354e565b61224160c954610100900460ff1660021490565b610de15760405163bae6e2a960e01b815260040160405180910390fd5b610db56124a8565b600183015460609065ffffffffffff80821691600160301b900481169085168211806122a257508065ffffffffffff168565ffffffffffff1610155b806122b3575065ffffffffffff8416155b1561231c57604080515f8082526020820190925290612312565b6122ff6040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b8152602001906001900390816122cd5790505b5092505050610f0e565b5f61233465ffffffffffff8784038116908716613572565b9050806001600160401b0381111561234e5761234e614264565b6040519080825280602002602001820160405280156123b157816020015b61239e6040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b81526020019060019003908161236c5790505b5093505f5b8181101561249d5765ffffffffffff871681015f90815260208981526040918290208251808401845281546001600160401b031681528351600183018054608081870284018101909752606083018181529396949587019492939192849291849184018282801561244457602002820191905f5260205f20905b815481526020019060010190808311612430575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff16604090910152905250855186908390811061248a5761248a61525a565b60209081029190910101526001016123b6565b505050509392505050565b6033546001600160a01b03163314610de15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d3d565b8060fe5f6125307f00000000000000000000000000000000000000000000000000000000000000008661530b565b65ffffffffffff16815260208101919091526040015f20555050565b80606001516001600160a01b0316815f015165ffffffffffff167f7c4c4523e17533e451df15762a093e0693a2cd8b279fe54c6cd3777ed5771213836080015184604001518560e001518661010001516040516125ac94939291906153a9565b60405180910390a350565b606580546001600160a01b0319169055610ca481613586565b6125e460c954610100900460ff1660021490565b15610de15760405163bae6e2a960e01b815260040160405180910390fd5b61263b60408051606080820183525f80835283519182018452808252602082810182905293820152909182019081525f60209091015290565b60208281015160d01c82526026830151828201805160f092831c90526028850151815190831c930192909252602a840151915160e89290921c604092830152602d9093015190921c9181019190915290565b805165ffffffffffff1615806126ac5750805165ffffffffffff164211155b610ca45760405163559895a360e01b815260040160405180910390fd5b60408051610120810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201929092526101008101919091528265ffffffffffff16431161273b576040516349517a1d60e11b815260040160405180910390fd5b81840365ffffffffffff167f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff161161278d5760405163eaabac9b60e01b815260040160405180910390fd5b5f6127a033896040015161ffff166135d7565b905060405180604001604052805f151581526020016127c28a602001516137d0565b9052815180515f1981019081106127db576127db61525a565b60200260200101819052505f81602001516128fb57604051635600026d60e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ac0004da906128409033908c908c906004016153d8565b6020604051808303815f875af115801561285c573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061288091906153fc565b90506001600160401b037f000000000000000000000000000000000000000000000000000000000000000016156128fb576128de610101337f0000000000000000000000000000000000000000000000000000000000000000613911565b6128fb5760405163e92c469f60e01b815260040160405180910390fd5b5f6001430390506040518061012001604052808865ffffffffffff1681526020014265ffffffffffff1681526020018365ffffffffffff168152602001336001600160a01b0316815260200161295b60018a0365ffffffffffff16611423565b815265ffffffffffff831660208201529140604083015260ff7f0000000000000000000000000000000000000000000000000000000000000000166060830152925160809091015250979650505050505050565b5f816040516020016129c19190615417565b604051602081830303815290604052805190602001209050919050565b805160c08101515160609190603a02608201806001600160401b03811115612a0857612a08614264565b6040519080825280601f01601f191660200182016040528015612a32576020820181803683370190505b50825160d090811b602083810191909152840151602683015260408401516046830152606080850151901b606683015260808085015190911b607a83015260a0808501519183019190915260c084015151919450840190612a929061395c565b60c08301515160f01b81526002015f5b8360c0015151811015612ae057612ad6828560c001518381518110612ac957612ac961525a565b602002602001015161397f565b9150600101612aa2565b50505050919050565b5f6001600160a01b038516612b115760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0386165f908152602089905260408120805490916001600160401b039182169187168210612b465786612b48565b815b8354909150600160401b900465ffffffffffff161580612b8a57508254612b7f908690600160401b900465ffffffffffff166154e7565b65ffffffffffff1642105b15612bcb576001600160401b038616612ba38284615505565b6001600160401b03161015612bcb576040516321f68cc160e21b815260040160405180910390fd5b612bd68b8a836139a8565b9350816001600160401b0316846001600160401b0316148015612c0857508254600160401b900465ffffffffffff1615155b15612c1e57825465ffffffffffff60401b191683555b612c3c88612c2b8661340a565b6001600160a01b038d169190613a31565b6040516001600160401b03851681526001600160a01b038a16907f3362c96009316515fccd3dd29c7036c305ad9e892d83dd5681845ac9edb0c9a89060200160405180910390a2505050979650505050505050565b6001600160a01b0382165f908152602084815260408083208151808301909252546001600160401b038116808352600160401b90910465ffffffffffff16928201929092529103612cf557604051634555262b60e01b815260040160405180910390fd5b602081015165ffffffffffff1615612d205760405163fb52063b60e01b815260040160405180910390fd5b65ffffffffffff4281811660208085019182526001600160a01b0387165f8181529189905260409091208551815493518616600160401b026dffffffffffffffffffffffffffff199094166001600160401b039091161792909217909155917f3bbe41cfdd142e0f9b2224dac18c6efd2a6966e35a9ec23ab57ce63a60b3360491612dad91861690615524565b60405165ffffffffffff909116815260200160405180910390a250505050565b610db582825a613a61565b60408051610100810182525f60208083018281529383018281526060808501848152608080870186815260a080890188815260c08a0198895260e08a018690528a8a52968b015160d090811c909a5260268b015190955260468a0151909252606689015190921c9052607a87015190951c9091529284015190529082015160a283019060f01c806001600160401b03811115612e7657612e76614264565b604051908082528060200260200182016040528015612ebf57816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181612e945790505b50835160c001525f5b8161ffff16811015612f3e5760408051606080820183525f80835260208301818152938301908152865190911c8252601486015160d01c909252601a850151909152603a8401855160c00151805184908110612f2657612f2661525a565b60209081029190910101919091529250600101612ec8565b505050919050565b604082015160c082015151905f90819060010165ffffffffffff1683612f7f5760405163c2e5347d60e01b815260040160405180910390fd5b845165ffffffffffff16811015612fa9576040516363db3a4160e01b815260040160405180910390fd5b845186515f1965ffffffffffff9283168701019450168310612fde5760405163677c56f160e01b815260040160405180910390fd5b80831015612fff5760405163181432e760e11b815260040160405180910390fd5b845f015165ffffffffffff1681039150509250925092565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661304d57505f610c38565b604051633326844b60e11b81526001600160a01b0384811660048301525f9182917f0000000000000000000000000000000000000000000000000000000000000000169063664d0896906024016040805180830381865afa1580156130b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130d89190615537565b91509150805f036130ed575f92505050610c38565b8161313a577f000000000000000000000000000000000000000000000000000000000000000065ffffffffffff16841161313a5760405163c1a58f1960e01b815260040160405180910390fd5b506001949350505050565b5f6131ec7f000000000000000000000000000000000000000000000000000000000000000060fc5f0160129054906101000a900465ffffffffffff160165ffffffffffff167f00000000000000000000000000000000000000000000000000000000000000008560c001518565ffffffffffff16815181106131c9576131c961525a565b6020026020010151602001510165ffffffffffff16613aa490919063ffffffff16565b90508042116131fa57505050565b6116f18360c001518365ffffffffffff168151811061321b5761321b61525a565b602090810291909101015151606085015161010191907f0000000000000000000000000000000000000000000000000000000000000000613ab9565b60c081015180515f919060096003820201836132838260408051828152600190920160051b8201905290565b6020808201529050855165ffffffffffff166040820152602086015160608201526040860151608082015260608601516001600160a01b031660a0820152608086015165ffffffffffff1660c082015260a086015160e082015260e0610100820152610120810183905260095f5b84811015613364575f86828151811061330c5761330c61525a565b602090810291909101015180516001600160a01b03166001850160051b8601529050602081015165ffffffffffff166002840160051b85015260408101516003840160051b85015250600391909101906001016132f1565b50815160051b602083012061338b8380516040516001820160051b83011490151060061b52565b979650505050505050565b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b6001600160a01b0382165f90815260208490526040902080546133e99083906001600160401b0316615563565b815467ffffffffffffffff19166001600160401b0391909116179055505050565b5f610c38633b9aca006001600160401b038416615582565b6040516001600160a01b038085166024830152831660448201526064810182905261141d9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613b76565b5f54610100900460ff16610de15760405162461bcd60e51b8152600401610d3d906152c0565b6001600160a01b0381163b6135205760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610d3d565b5f5160206155f85f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b61355783613c49565b5f825111806135635750805b156116f15761141d8383613c88565b5f8183116135805782610f0e565b50919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60408051808201909152606081525f60208201526101005460ff9065ffffffffffff80821691600160301b9004811690828203165f8061361883600a613572565b90505f5b818110156136995765ffffffffffff80871682015f9081526020899052604090206002810154909163010000009091041680158061367f57507f000000000000000000000000000000000000000000000000000000000000000061ffff16810142105b1561368b575050613699565b50506001928301920161361c565b50818810156136bb5760405163014b3fdb60e11b815260040160405180910390fd5b5f6136d1600a6136cb8b87613572565b90613572565b9050806001016001600160401b038111156136ee576136ee614264565b60405190808252806020026020018201604052801561375157816020015b61373e6040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b81526020019060019003908161370c5790505b508089525f906137669089908d908a86613cad565b5065ffffffffffff167f000000000000000000000000000000000000000000000000000000000000000060ff167f000000000000000000000000000000000000000000000000000000000000000061ffff160201421160208a015250969998505050505050505050565b604080516060808201835281525f6020808301829052928201529082015161ffff1661380f5760405163fdac229f60e01b815260040160405180910390fd5b5f826020015161ffff166001600160401b0381111561383057613830614264565b604051908082528060200260200182016040528015613859578160200160208202803683370190505b5090505f5b836020015161ffff168110156138e157835161387f90829061ffff16615524565b498282815181106138925761389261525a565b6020026020010181815250508181815181106138b0576138b061525a565b60200260200101515f5f1b036138d957604051637bb2fa2f60e11b815260040160405180910390fd5b60010161385e565b50604080516060810182529182529283015162ffffff16602082015265ffffffffffff4216928101929092525090565b6001600160a01b0382165f90815260208490526040812080546001600160401b0380851691161080159061395357508054600160401b900465ffffffffffff16155b95945050505050565b61ffff811115610ca45760405163161e7a6b60e11b815260040160405180910390fd5b805160601b8252602081015160d01b60148301526040810151601a8301908152603a8301610f0e565b6001600160a01b0382165f90815260208490526040812080546001600160401b038085169116116139f357805467ffffffffffffffff19811682556001600160401b03169150613a29565b8054839250613a0c9083906001600160401b0316615505565b815467ffffffffffffffff19166001600160401b03919091161781555b509392505050565b6040516001600160a01b0383166024820152604481018290526116f190849063a9059cbb60e01b90606401613456565b815f03613a6d57505050565b613a8783838360405180602001604052805f815250613e2b565b6116f157604051634c67134d60e11b815260040160405180910390fd5b5f818311613ab25781610f0e565b5090919050565b5f613ac58585846139a8565b9050806001600160401b03165f03613add575061141d565b5f613ae9600283615599565b90505f613af68284615505565b90506001600160401b03821615613b1257613b128786846133bc565b604080516001600160401b038681168252848116602083015283168183015290516001600160a01b0387811692908916917faa22f5157944b5fa6846460e159d57ea9c3878e71fda274af372fa2ccf285aa09181900360600190a350505050505050565b5f613bca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e689092919063ffffffff16565b905080515f1480613bea575080806020019051810190613bea91906155c6565b6116f15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d3d565b613c52816134b3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610f0e838360405180606001604052806027815260200161561860279139613e7e565b5f5f825f03613cc6575065ffffffffffff905082613e21565b5f5f5b84811015613db65765ffffffffffff861681015f90815260208a815260409182902082518084018452600180825284519083018054608081870284018101909752606083018181529496939586019492939192849290918491840182828015613d4f57602002820191905f5260205f20905b815481526020019060010190808311613d3b575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff1660409091015290528851899084908110613d9457613d9461525a565b6020908102919091010152546001600160401b03169190910190600101613cc9565b50613dd06001600160a01b038816633b9aca008302612dcd565b855f81518110613de257613de261525a565b602002602001015160200151604001519250838501915081886001015f6101000a81548165ffffffffffff021916908365ffffffffffff160217905550505b9550959350505050565b5f6001600160a01b038516613e5357604051634c67134d60e11b815260040160405180910390fd5b5f5f835160208501878988f195945050505050565b6060613e7684845f85613ef2565b949350505050565b60605f5f856001600160a01b031685604051613e9a91906155e1565b5f60405180830381855af49150503d805f8114613ed2576040519150601f19603f3d011682016040523d82523d5f602084013e613ed7565b606091505b5091509150613ee886838387613fba565b9695505050505050565b606082471015613f535760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610d3d565b5f5f866001600160a01b03168587604051613f6e91906155e1565b5f6040518083038185875af1925050503d805f8114613fa8576040519150601f19603f3d011682016040523d82523d5f602084013e613fad565b606091505b509150915061338b878383875b606083156140285782515f03614021576001600160a01b0385163b6140215760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d3d565b5081613e76565b613e76838381511561403d5781518083602001fd5b8060405162461bcd60e51b8152600401610d3d91906140dd565b6001600160a01b0381168114610ca4575f5ffd5b803561407681614057565b919050565b5f6020828403121561408b575f5ffd5b8135610f0e81614057565b5f60a08284031280156140a7575f5ffd5b509092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610f0e60208301846140af565b6001600160401b0381168114610ca4575f5ffd5b5f60208284031215614113575f5ffd5b8135610f0e816140ef565b65ffffffffffff81168114610ca4575f5ffd5b80356140768161411e565b5f5f6040838503121561414d575f5ffd5b82356141588161411e565b915060208301356141688161411e565b809150509250929050565b8051606080845281519084018190525f9160200190829060808601905b808310156141b35783518252602082019150602084019350600183019250614190565b5062ffffff602086015116602087015265ffffffffffff604086015116604087015280935050505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561425857603f1987860301845281516001600160401b03815116865260208101519050604060208701526142426040870182614173565b9550506020938401939190910190600101614207565b50929695505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561429a5761429a614264565b60405290565b604080519081016001600160401b038111828210171561429a5761429a614264565b60405161012081016001600160401b038111828210171561429a5761429a614264565b60405160c081016001600160401b038111828210171561429a5761429a614264565b60405160e081016001600160401b038111828210171561429a5761429a614264565b604051601f8201601f191681016001600160401b038111828210171561435157614351614264565b604052919050565b5f5f6040838503121561436a575f5ffd5b823561437581614057565b915060208301356001600160401b0381111561438f575f5ffd5b8301601f8101851361439f575f5ffd5b80356001600160401b038111156143b8576143b8614264565b6143cb601f8201601f1916602001614329565b8181528660208385010111156143df575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f6020828403121561440e575f5ffd5b5035919050565b5f5f83601f840112614425575f5ffd5b5081356001600160401b0381111561443b575f5ffd5b602083019150836020828501011115614452575f5ffd5b9250929050565b5f5f5f5f6040858703121561446c575f5ffd5b84356001600160401b03811115614481575f5ffd5b61448d87828801614415565b90955093505060208501356001600160401b038111156144ab575f5ffd5b6144b787828801614415565b95989497509550505050565b5f5f602083850312156144d4575f5ffd5b82356001600160401b038111156144e9575f5ffd5b6144f585828601614415565b90969095509350505050565b815165ffffffffffff16815260208083015160a08301916145489084018261ffff815116825261ffff602082015116602083015262ffffff60408201511660408301525050565b5061ffff604084015116608083015292915050565b5f6020828403121561456d575f5ffd5b81356001600160401b03811115614582575f5ffd5b82016101208185031215610f0e575f5ffd5b81516001600160a01b03168152610220810160208301516145c060208401826001600160a01b03169052565b5060408301516145db60408401826001600160a01b03169052565b5060608301516145f660608401826001600160a01b03169052565b50608083015161461160808401826001600160a01b03169052565b5060a083015161462c60a08401826001600160401b03169052565b5060c083015161464760c08401826001600160401b03169052565b5060e083015161466160e084018265ffffffffffff169052565b5061010083015161467d61010084018265ffffffffffff169052565b5061012083015161469961012084018265ffffffffffff169052565b506101408301516146b561014084018265ffffffffffff169052565b506101608301516146d161016084018265ffffffffffff169052565b506101808301516146e861018084018260ff169052565b506101a08301516147006101a084018261ffff169052565b506101c083015161471d6101c08401826001600160401b03169052565b506101e083015161473a6101e08401826001600160401b03169052565b5061020083015161475161020084018260ff169052565b5092915050565b5f60208284031215614768575f5ffd5b81356001600160401b0381111561477d575f5ffd5b820160208185031215610f0e575f5ffd5b5f5f6040838503121561479f575f5ffd5b82356147aa81614057565b91506020830135614168816140ef565b803561ffff81168114614076575f5ffd5b62ffffff81168114610ca4575f5ffd5b8035614076816147cb565b5f606082840312156147f6575f5ffd5b6147fe614278565b9050614809826147ba565b8152614817602083016147ba565b6020820152604082013561482a816147cb565b604082015292915050565b5f60608284031215614845575f5ffd5b610f0e83836147e6565b5f8151808452602084019350602083015f5b828110156148a957815180516001600160a01b0316875260208082015165ffffffffffff16818901526040918201519188019190915260609096019590910190600101614861565b5093949350505050565b602081525f825160208084015265ffffffffffff8151166040840152602081015160608401526040810151608084015260018060a01b0360608201511660a084015265ffffffffffff60808201511660c084015260a081015160e084015260c0810151905060e0610100840152613e7661012084018261484f565b5f6020828403121561493e575f5ffd5b81356001600160401b03811115614953575f5ffd5b820160e08185031215610f0e575f5ffd5b5f60a0828403128015614975575f5ffd5b5061497e614278565b82356149898161411e565b815261499884602085016147e6565b60208201526149a9608084016147ba565b60408201529392505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b80516140768161411e565b805161407681614057565b60ff81168114610ca4575f5ffd5b805161407681614a63565b5f6001600160401b03821115614a9457614a94614264565b5060051b60200190565b8015158114610ca4575f5ffd5b8051614076816147cb565b5f82601f830112614ac5575f5ffd5b8151614ad8614ad382614a7c565b614329565b8082825260208201915060208360051b860101925085831115614af9575f5ffd5b602085015b83811015614c3b5780516001600160401b03811115614b1b575f5ffd5b86016040818903601f19011215614b30575f5ffd5b614b386142a0565b6020820151614b4681614a9e565b815260408201516001600160401b03811115614b60575f5ffd5b6020818401019250506060828a031215614b78575f5ffd5b614b80614278565b82516001600160401b03811115614b95575f5ffd5b8301601f81018b13614ba5575f5ffd5b8051614bb3614ad382614a7c565b8082825260208201915060208360051b85010192508d831115614bd4575f5ffd5b6020840193505b82841015614bf6578351825260209384019390910190614bdb565b845250614c0891505060208401614aab565b6020820152614c1960408401614a4d565b6040820152806020830152508085525050602083019250602081019050614afe565b5095945050505050565b5f6101208284031215614c56575f5ffd5b614c5e6142c2565b9050614c6982614a4d565b8152614c7760208301614a4d565b6020820152614c8860408301614a4d565b6040820152614c9960608301614a58565b606082015260808281015190820152614cb460a08301614a4d565b60a082015260c08281015190820152614ccf60e08301614a71565b60e08201526101008201516001600160401b03811115614ced575f5ffd5b614cf984828501614ab6565b6101008301525092915050565b5f5f5f5f848603610120811215614d1b575f5ffd5b8551614d268161411e565b945060c0601f1982011215614d39575f5ffd5b50614d426142e5565b6020860151614d508161411e565b81526040860151614d608161411e565b60208201526060860151614d738161411e565b60408201526080860151614d868161411e565b606082015260a0860151614d998161411e565b608082015260c086015160a082015260e08601519093506001600160401b03811115614dc3575f5ffd5b614dcf87828801614c45565b61010096909601519497939650505050565b634e487b7160e01b5f52601260045260245ffd5b5f82614e0357614e03614de1565b500690565b803561407681614a63565b5f82601f830112614e22575f5ffd5b8135614e30614ad382614a7c565b8082825260208201915060208360051b860101925085831115614e51575f5ffd5b602085015b83811015614c3b5780356001600160401b03811115614e73575f5ffd5b86016040818903601f19011215614e88575f5ffd5b614e906142a0565b6020820135614e9e81614a9e565b815260408201356001600160401b03811115614eb8575f5ffd5b6020818401019250506060828a031215614ed0575f5ffd5b614ed8614278565b82356001600160401b03811115614eed575f5ffd5b8301601f81018b13614efd575f5ffd5b8035614f0b614ad382614a7c565b8082825260208201915060208360051b85010192508d831115614f2c575f5ffd5b6020840193505b82841015614f4e578335825260209384019390910190614f33565b845250614f60915050602084016147db565b6020820152614f7160408401614131565b6040820152806020830152508085525050602083019250602081019050614e56565b5f6101208236031215614fa4575f5ffd5b614fac6142c2565b614fb583614131565b8152614fc360208401614131565b6020820152614fd460408401614131565b6040820152614fe56060840161406b565b60608201526080838101359082015261500060a08401614131565b60a082015260c0838101359082015261501b60e08401614e08565b60e08201526101008301356001600160401b03811115615039575f5ffd5b614cf936828601614e13565b5f82601f830112615054575f5ffd5b8135615062614ad382614a7c565b80828252602082019150602060608402860101925085831115615083575f5ffd5b602085015b83811015614c3b576060818803121561509f575f5ffd5b6150a7614278565b81356150b281614057565b815260208201356150c28161411e565b602082810191909152604083810135908301529084529290920191606001615088565b5f60e082840312156150f5575f5ffd5b6150fd614307565b905061510882614131565b8152602082810135908201526040808301359082015261512a6060830161406b565b606082015261513b60808301614131565b608082015260a0828101359082015260c08201356001600160401b03811115615162575f5ffd5b61516e84828501615045565b60c08301525092915050565b5f6020823603121561518a575f5ffd5b604051602081016001600160401b03811182821017156151ac576151ac614264565b60405282356001600160401b038111156151c4575f5ffd5b6151d0368286016150e5565b82525092915050565b8481526001600160401b0384811660208301528316604082015260c08101613953606083018461ffff815116825261ffff602082015116602083015262ffffff60408201511660408301525050565b5f60208284031215615238575f5ffd5b5051919050565b5f6020828403121561524f575f5ffd5b8151610f0e816140ef565b634e487b7160e01b5f52603260045260245ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b848152836020820152606060408201525f613ee860608301848661526e565b5f610c3836836150e5565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f65ffffffffffff83168061532257615322614de1565b8065ffffffffffff84160691505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561539d57601f19858403018852815180511515845260208101519050604060208501526153866040850182614173565b6020998a0199909450929092019150600101615352565b50909695505050505050565b84815265ffffffffffff8416602082015260ff83166040820152608060608201525f613ee86080830184615336565b6001600160a01b03841681526040602082018190525f90613953908301848661526e565b5f6020828403121561540c575f5ffd5b8151610f0e8161411e565b6020815261543060208201835165ffffffffffff169052565b5f602083015161544a604084018265ffffffffffff169052565b50604083015165ffffffffffff811660608401525060608301516001600160a01b038116608084015250608083015160a083015260a083015161549760c084018265ffffffffffff169052565b5060c083015160e083015260e08301516154b761010084018260ff169052565b5061010083015161012080840152613e76610140840182615336565b634e487b7160e01b5f52601160045260245ffd5b65ffffffffffff8181168382160190811115610c3857610c386154d3565b6001600160401b038281168282160390811115610c3857610c386154d3565b80820180821115610c3857610c386154d3565b5f5f60408385031215615548575f5ffd5b825161555381614a9e565b6020939093015192949293505050565b6001600160401b038181168382160190811115610c3857610c386154d3565b8082028115828204841417610c3857610c386154d3565b5f6001600160401b038316806155b1576155b1614de1565b806001600160401b0384160491505092915050565b5f602082840312156155d6575f5ffd5b8151610f0e81614a9e565b5f82518060208501845e5f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d51ec19498c6238096cd20d98216f63ecca74c5a280a1ce7597db8e00f005efa64736f6c634300081e00330000000000000000000000004c7a8b639edf48b2cb254bdb1a1c76558933c20c00000000000000000000000083950e54c2d1659c184ceb43f906c310b27b7542000000000000000000000000a4e7bf2f4f27989aa0a6b7d692edd195048fd2500000000000000000000000004e5099105ab4c73cf227abcdd0d5e1802ae936dc000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af0
Deployed ByteCode
0x60806040526004361061021d575f3560e01c80638456cb591161011e578063d6dad060116100a8578063ea1917431161006d578063ea19174314610b2d578063edbacd4414610b4c578063efba83c914610b78578063f2fde38b14610b97578063f954ab9214610bb6575f5ffd5b8063d6dad06014610a9e578063dbaf214514610abd578063df596d9e14610ad1578063e305333514610ae4578063e30c397814610b10575f5ffd5b8063a834725a116100ee578063a834725a14610659578063afb63ad414610678578063b28e824e146106a4578063c3f909d4146106c3578063c595459714610a7f575f5ffd5b80638456cb59146105f55780638abf6077146106095780638da5cb5b1461061d5780639791e6441461063a575f5ffd5b80633f4ba83a116101aa5780635c975abb1161016f5780635c975abb146104645780635ccc1718146104845780636aa6a01a146104ba578063715018a6146105cd57806379ba5097146105e1575f5ffd5b80633f4ba83a146103d057806340df9866146103e45780634f1ef2861461041057806352d1902d1461042357806359db6e8514610445575f5ffd5b806313765838116101f0578063137658381461031857806319ab453c1461033957806322611280146103585780633075db561461036c5780633659cfe6146103b1575f5ffd5b80630423c7de1461022157806304f3bcec1461025b5780630d8912f3146102a15780631275a673146102ec575b5f5ffd5b34801561022c575f5ffd5b5060fb5461023f9065ffffffffffff1681565b60405165ffffffffffff90911681526020015b60405180910390f35b348015610266575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610252565b3480156102ac575f5ffd5b506102c06102bb36600461407b565b610bd5565b6040805182516001600160401b0316815260209283015165ffffffffffff169281019290925201610252565b3480156102f7575f5ffd5b5061030b610306366004614096565b610c3e565b60405161025291906140dd565b348015610323575f5ffd5b50610337610332366004614103565b610c57565b005b348015610344575f5ffd5b5061033761035336600461407b565b610ca7565b348015610363575f5ffd5b50610337610db9565b348015610377575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b6040519015158152602001610252565b3480156103bc575f5ffd5b506103376103cb36600461407b565b610de3565b3480156103db575f5ffd5b50610337610ea7565b3480156103ef575f5ffd5b506104036103fe36600461413c565b610f00565b60405161025291906141e1565b61033761041e366004614359565b610f15565b34801561042e575f5ffd5b50610437610fca565b604051908152602001610252565b348015610450575f5ffd5b5061033761045f3660046143fe565b61107b565b34801561046f575f5ffd5b506103a160c954610100900460ff1660021490565b34801561048f575f5ffd5b50610100546040805165ffffffffffff8084168252600160301b909304909216602083015201610252565b3480156104c5575f5ffd5b5061055a6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260fc5465ffffffffffff8082168352600160301b820481166020840152600160601b8204811693830193909352600160901b810483166060830152600160c01b9004909116608082015260fd5460a082015290565b60405161025291905f60c08201905065ffffffffffff835116825265ffffffffffff602084015116602083015265ffffffffffff604084015116604083015265ffffffffffff606084015116606083015265ffffffffffff608084015116608083015260a083015160a083015292915050565b3480156105d8575f5ffd5b50610337611227565b3480156105ec575f5ffd5b50610337611238565b348015610600575f5ffd5b506103376112af565b348015610614575f5ffd5b50610289611304565b348015610628575f5ffd5b506033546001600160a01b0316610289565b348015610645575f5ffd5b50610337610654366004614459565b611312565b348015610664575f5ffd5b506104376106733660046143fe565b611423565b348015610683575f5ffd5b506106976106923660046144c3565b61146e565b6040516102529190614501565b3480156106af575f5ffd5b506104376106be36600461455d565b6114e5565b3480156106ce575f5ffd5b50610a7260408051610220810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091526040518061022001604052807f0000000000000000000000004c7a8b639edf48b2cb254bdb1a1c76558933c20c6001600160a01b031681526020017f00000000000000000000000083950e54c2d1659c184ceb43f906c310b27b75426001600160a01b031681526020017f000000000000000000000000a4e7bf2f4f27989aa0a6b7d692edd195048fd2506001600160a01b031681526020017f0000000000000000000000004e5099105ab4c73cf227abcdd0d5e1802ae936dc6001600160a01b031681526020017f000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af06001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f0000000000000000000000000000000000000000000000000000000000093a8065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000384065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000006978065ffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000b465ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000098968065ffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000004b60ff1681526020017f000000000000000000000000000000000000000000000000000000000000000061ffff1681526020017f00000000000000000000000000000000000000000000000000000000000f42406001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000326001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000a060ff16815250905090565b6040516102529190614594565b348015610a8a575f5ffd5b5061030b610a99366004614758565b6114f7565b348015610aa9575f5ffd5b50610337610ab836600461478e565b61150a565b348015610ac8575f5ffd5b50610337611598565b610337610adf366004614835565b6115d7565b348015610aef575f5ffd5b50610af86116f6565b6040516001600160401b039091168152602001610252565b348015610b1b575f5ffd5b506065546001600160a01b0316610289565b348015610b38575f5ffd5b50610337610b47366004614459565b6117c1565b348015610b57575f5ffd5b50610b6b610b663660046144c3565b611ca8565b60405161025291906148b3565b348015610b83575f5ffd5b50610337610b9236600461478e565b611d25565b348015610ba2575f5ffd5b50610337610bb136600461407b565b611d71565b348015610bc1575f5ffd5b50610437610bd036600461492e565b611de2565b6040805180820182525f80825260208083018290528351808501855282815281018290526001600160a01b03851682526101018152908390208351808501909452546001600160401b0381168452600160401b900465ffffffffffff1690830152905b92915050565b6060610c38610c5236849003840184614964565b611df4565b610c5f611e5d565b610c696002611ea2565b610c9a6101017f000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af03380856001611eab565b610ca46001611ea2565b50565b5f54610100900460ff1615808015610cc557505f54600160ff909116105b80610cde5750303b158015610cde57505f5460ff166001145b610d465760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015610d67575f805461ff0019166101001790555b610d7082611fb0565b8015610db5575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b610dc1611e5d565b610dcb6002611ea2565b610dd76101013361200e565b610de16001611ea2565b565b6001600160a01b037f000000000000000000000000f5b72db1ccebd78892d19ef2c48d9ce6cfada98b163003610e2b5760405162461bcd60e51b8152600401610d3d906149b5565b7f000000000000000000000000f5b72db1ccebd78892d19ef2c48d9ce6cfada98b6001600160a01b0316610e5d6120a0565b6001600160a01b031614610e835760405162461bcd60e51b8152600401610d3d90614a01565b610e8c816120bb565b604080515f80825260208201909252610ca4918391906120c3565b610eaf61222d565b610ec360c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a1610de1335f61225e565b6060610f0e60ff8484612266565b9392505050565b6001600160a01b037f000000000000000000000000f5b72db1ccebd78892d19ef2c48d9ce6cfada98b163003610f5d5760405162461bcd60e51b8152600401610d3d906149b5565b7f000000000000000000000000f5b72db1ccebd78892d19ef2c48d9ce6cfada98b6001600160a01b0316610f8f6120a0565b6001600160a01b031614610fb55760405162461bcd60e51b8152600401610d3d90614a01565b610fbe826120bb565b610db5828260016120c3565b5f306001600160a01b037f000000000000000000000000f5b72db1ccebd78892d19ef2c48d9ce6cfada98b16146110695760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610d3d565b505f5160206155f85f395f51905f5290565b6110836124a8565b60fb54604051633dd0723360e21b81526004810183905265ffffffffffff90911660248201525f9081908190819073aad95c58d4b8ceacdb6717413309e764a28fb5579063f741c8cc906044015f60405180830381865af41580156110ea573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526111119190810190614d06565b60fb805465ffffffffffff191665ffffffffffff86811691909117909155835160fc805460208701516040880151606089015160808a01519587166bffffffffffffffffffffffff1990941693909317600160301b92871692909202919091176bffffffffffffffffffffffff60601b1916600160601b9186169190910265ffffffffffff60901b191617600160901b918516919091021765ffffffffffff60c01b1916600160c01b929093169190910291909117905560a083015160fd55929650909450925090506111e45f82612502565b6111ed8261254c565b6040518581527fe4356761c97932c05c3ee0859fb1a5e4f91f7a1d7a3752c7d5a72d5cc6ecb2d29060200160405180910390a15050505050565b61122f6124a8565b610de15f6125b7565b60655433906001600160a01b031681146112a65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610d3d565b610ca4816125b7565b6112b76125d0565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a1610de133600161225e565b5f61130d6120a0565b905090565b61131a611e5d565b6113246002611ea2565b5f61136383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260292505050565b905061136e8161268d565b60fc5465ffffffffffff80821691600160301b8104821691600160601b90910416826113ad5760405163ba74d80f60e01b815260040160405180910390fd5b5f6113bc858a8a8787876126c9565b60fc80544365ffffffffffff908116600160301b026bffffffffffffffffffffffff19909216600189019190911617179055805190915061140590611400836129af565b612502565b61140e8161254c565b505050505061141d6001611ea2565b50505050565b5f60fe8161145965ffffffffffff7f00000000000000000000000000000000000000000000000000000000009896801685614df5565b81526020019081526020015f20549050919050565b6114a760408051606080820183525f80835283519182018452808252602082810182905293820152909182019081525f60209091015290565b610f0e83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061260292505050565b5f610c386114f283614f93565b6129af565b6060610c386115058361517a565b6129de565b611512611e5d565b61151c6002611ea2565b61158d6101017f000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af03385857f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000093a80612ae9565b50610db56001611ea2565b6115a0611e5d565b6115aa6002611ea2565b610dd7610101337f0000000000000000000000000000000000000000000000000000000000093a80612c91565b60015f5260fe6020527f457c8a48b4735f56b938837eb0a8a5f9c55f23c1a85767ce3b65c3e59d3d32b754806116205760405163f37a8b1360e01b815260040160405180910390fd5b6040516312b2aa9160e31b81525f90735912bae0b1f53f15c2cba5f9ab3718ddda2a6046906395955488906116a09060ff907f00000000000000000000000000000000000000000000000000000000000f4240907f00000000000000000000000000000000000000000000000000000000000000329089906004016151d9565b602060405180830381865af41580156116bb573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116df9190615228565b905080156116f1576116f13382612dcd565b505050565b6040516343c3d71960e01b815260ff60048201526001600160401b037f00000000000000000000000000000000000000000000000000000000000f4240811660248301527f00000000000000000000000000000000000000000000000000000000000000321660448201525f90735912bae0b1f53f15c2cba5f9ab3718ddda2a6046906343c3d71990606401602060405180830381865af415801561179d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061130d919061523f565b6117c9611e5d565b6117d36002611ea2565b6040805160c08101825260fc5465ffffffffffff8082168352600160301b82048116602080850191909152600160601b8304821684860152600160901b830482166060850152600160c01b90920416608083015260fd5460a08301528251601f870182900482028101820190935285835290915f9161186c919088908890819084018382808284375f92019190915250612dd892505050565b80519091505f808061187e8685612f46565b9250925092505f8460c001518265ffffffffffff16815181106118a3576118a361525a565b60200260200101516020015165ffffffffffff16420390505f6118c63383613017565b90505f65ffffffffffff841615611909578660c001516001850365ffffffffffff16815181106118f8576118f861525a565b60200260200101516040015161190f565b86602001515b9050808960a00151146119355760405163198070b360e01b815260040160405180910390fd5b61193e85611423565b8760400151146119615760405163f904c2fd60e01b815260040160405180910390fd5b81611970576119708785613145565b7f0000000000000000000000004e5099105ab4c73cf227abcdd0d5e1802ae936dc6001600160a01b031663c9a0b8c860405180606001604052808a6080015165ffffffffffff1681526020018a60c0015160018b03815181106119d5576119d561525a565b60200260200101516040015181526020018a60a001518152506040518263ffffffff1660e01b8152600401611a2e9190815165ffffffffffff168152602080830151908201526040918201519181019190915260600190565b5f604051808303815f87803b158015611a45575f5ffd5b505af1158015611a57573d5f5f3e3d5ffd5b50505065ffffffffffff42811660808c0181905290871660408c015260608b01525060c087015180515f198801908110611a9357611a9361525a565b6020026020010151604001518960a00181815250508860fc5f820151815f015f6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506020820151815f0160066101000a81548165ffffffffffff021916908365ffffffffffff1602179055506040820151815f01600c6101000a81548165ffffffffffff021916908365ffffffffffff1602179055506060820151815f0160126101000a81548165ffffffffffff021916908365ffffffffffff1602179055506080820151815f0160186101000a81548165ffffffffffff021916908365ffffffffffff16021790555060a0820151816001015590505086606001516001600160a01b03167fa274dcaff3629ec7d69d144038e97732516ff306fcbf8a2bc9423d106779a2f0885f0151868a5f01510188604051611bee9392919065ffffffffffff93841681529183166020830152909116604082015260600190565b60405180910390a27f0000000000000000000000004c7a8b639edf48b2cb254bdb1a1c76558933c20c6001600160a01b03166314bcf3dd8565ffffffffffff168803600114611c3d575f611c3f565b845b611c488a613257565b8e8e6040518563ffffffff1660e01b8152600401611c699493929190615296565b5f6040518083038186803b158015611c7f575f5ffd5b505afa158015611c91573d5f5f3e3d5ffd5b5050505050505050505050505061141d6001611ea2565b60408051610100810182525f6020820181815292820181905260608083018290526080830182905260a0830182905260c083019190915260e0820152908152610f0e83838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612dd892505050565b611d2d611e5d565b611d376002611ea2565b611d676101017f000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af03385855f611eab565b610db56001611ea2565b611d796124a8565b606580546001600160a01b0383166001600160a01b03199091168117909155611daa6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f610c38611def836152b5565b613257565b60408051600f8082528183019092526060916020820181803683375050835160d01b60208084019190915284810180515160f090811b6026860152815190920151821b60288501525160409081015160e81b602a8501529094015190931b602d82015292915050565b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff1603610de15760405163dfc60d8560e01b815260040160405180910390fd5b610ca481613396565b6001600160a01b038316611ed25760405163e6c4247b60e01b815260040160405180910390fd5b611edd8684846133bc565b808015611f0f57506001600160a01b0383165f90815260208790526040902054600160401b900465ffffffffffff1615155b15611f3c576001600160a01b0383165f908152602087905260409020805465ffffffffffff60401b191690555b611f5c8430611f4a8561340a565b6001600160a01b038916929190613422565b6040516001600160401b03831681526001600160a01b0380851691908616907fe5e95641fa87bdfef3ce0d39f0c9a37c200f3bf59f53623b3de21e03ed33e3d29060200160405180910390a3505050505050565b5f54610100900460ff16611fd65760405162461bcd60e51b8152600401610d3d906152c0565b611fde61348d565b611ffc6001600160a01b03821615611ff657816125b7565b336125b7565b5060c9805461ff001916610100179055565b6001600160a01b0381165f90815260208390526040812080549091600160401b90910465ffffffffffff169003612058576040516387bdc6a960e01b815260040160405180910390fd5b805465ffffffffffff60401b191681556040516001600160a01b038316907fc51fdb96728de385ec7859819e3997bc618362ef0dbca0ad051d856866cda3db905f90a2505050565b5f5160206155f85f395f51905f52546001600160a01b031690565b610ca46124a8565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156120f6576116f1836134b3565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612150575060408051601f3d908101601f1916820190925261214d91810190615228565b60015b6121b35760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610d3d565b5f5160206155f85f395f51905f5281146122215760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610d3d565b506116f183838361354e565b61224160c954610100900460ff1660021490565b610de15760405163bae6e2a960e01b815260040160405180910390fd5b610db56124a8565b600183015460609065ffffffffffff80821691600160301b900481169085168211806122a257508065ffffffffffff168565ffffffffffff1610155b806122b3575065ffffffffffff8416155b1561231c57604080515f8082526020820190925290612312565b6122ff6040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b8152602001906001900390816122cd5790505b5092505050610f0e565b5f61233465ffffffffffff8784038116908716613572565b9050806001600160401b0381111561234e5761234e614264565b6040519080825280602002602001820160405280156123b157816020015b61239e6040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b81526020019060019003908161236c5790505b5093505f5b8181101561249d5765ffffffffffff871681015f90815260208981526040918290208251808401845281546001600160401b031681528351600183018054608081870284018101909752606083018181529396949587019492939192849291849184018282801561244457602002820191905f5260205f20905b815481526020019060010190808311612430575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff16604090910152905250855186908390811061248a5761248a61525a565b60209081029190910101526001016123b6565b505050509392505050565b6033546001600160a01b03163314610de15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d3d565b8060fe5f6125307f00000000000000000000000000000000000000000000000000000000009896808661530b565b65ffffffffffff16815260208101919091526040015f20555050565b80606001516001600160a01b0316815f015165ffffffffffff167f7c4c4523e17533e451df15762a093e0693a2cd8b279fe54c6cd3777ed5771213836080015184604001518560e001518661010001516040516125ac94939291906153a9565b60405180910390a350565b606580546001600160a01b0319169055610ca481613586565b6125e460c954610100900460ff1660021490565b15610de15760405163bae6e2a960e01b815260040160405180910390fd5b61263b60408051606080820183525f80835283519182018452808252602082810182905293820152909182019081525f60209091015290565b60208281015160d01c82526026830151828201805160f092831c90526028850151815190831c930192909252602a840151915160e89290921c604092830152602d9093015190921c9181019190915290565b805165ffffffffffff1615806126ac5750805165ffffffffffff164211155b610ca45760405163559895a360e01b815260040160405180910390fd5b60408051610120810182525f8082526020820181905291810182905260608082018390526080820183905260a0820183905260c0820183905260e08201929092526101008101919091528265ffffffffffff16431161273b576040516349517a1d60e11b815260040160405180910390fd5b81840365ffffffffffff167f000000000000000000000000000000000000000000000000000000000098968065ffffffffffff161161278d5760405163eaabac9b60e01b815260040160405180910390fd5b5f6127a033896040015161ffff166135d7565b905060405180604001604052805f151581526020016127c28a602001516137d0565b9052815180515f1981019081106127db576127db61525a565b60200260200101819052505f81602001516128fb57604051635600026d60e11b81526001600160a01b037f00000000000000000000000083950e54c2d1659c184ceb43f906c310b27b7542169063ac0004da906128409033908c908c906004016153d8565b6020604051808303815f875af115801561285c573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061288091906153fc565b90506001600160401b037f000000000000000000000000000000000000000000000000000000000000000016156128fb576128de610101337f0000000000000000000000000000000000000000000000000000000000000000613911565b6128fb5760405163e92c469f60e01b815260040160405180910390fd5b5f6001430390506040518061012001604052808865ffffffffffff1681526020014265ffffffffffff1681526020018365ffffffffffff168152602001336001600160a01b0316815260200161295b60018a0365ffffffffffff16611423565b815265ffffffffffff831660208201529140604083015260ff7f000000000000000000000000000000000000000000000000000000000000004b166060830152925160809091015250979650505050505050565b5f816040516020016129c19190615417565b604051602081830303815290604052805190602001209050919050565b805160c08101515160609190603a02608201806001600160401b03811115612a0857612a08614264565b6040519080825280601f01601f191660200182016040528015612a32576020820181803683370190505b50825160d090811b602083810191909152840151602683015260408401516046830152606080850151901b606683015260808085015190911b607a83015260a0808501519183019190915260c084015151919450840190612a929061395c565b60c08301515160f01b81526002015f5b8360c0015151811015612ae057612ad6828560c001518381518110612ac957612ac961525a565b602002602001015161397f565b9150600101612aa2565b50505050919050565b5f6001600160a01b038516612b115760405163e6c4247b60e01b815260040160405180910390fd5b6001600160a01b0386165f908152602089905260408120805490916001600160401b039182169187168210612b465786612b48565b815b8354909150600160401b900465ffffffffffff161580612b8a57508254612b7f908690600160401b900465ffffffffffff166154e7565b65ffffffffffff1642105b15612bcb576001600160401b038616612ba38284615505565b6001600160401b03161015612bcb576040516321f68cc160e21b815260040160405180910390fd5b612bd68b8a836139a8565b9350816001600160401b0316846001600160401b0316148015612c0857508254600160401b900465ffffffffffff1615155b15612c1e57825465ffffffffffff60401b191683555b612c3c88612c2b8661340a565b6001600160a01b038d169190613a31565b6040516001600160401b03851681526001600160a01b038a16907f3362c96009316515fccd3dd29c7036c305ad9e892d83dd5681845ac9edb0c9a89060200160405180910390a2505050979650505050505050565b6001600160a01b0382165f908152602084815260408083208151808301909252546001600160401b038116808352600160401b90910465ffffffffffff16928201929092529103612cf557604051634555262b60e01b815260040160405180910390fd5b602081015165ffffffffffff1615612d205760405163fb52063b60e01b815260040160405180910390fd5b65ffffffffffff4281811660208085019182526001600160a01b0387165f8181529189905260409091208551815493518616600160401b026dffffffffffffffffffffffffffff199094166001600160401b039091161792909217909155917f3bbe41cfdd142e0f9b2224dac18c6efd2a6966e35a9ec23ab57ce63a60b3360491612dad91861690615524565b60405165ffffffffffff909116815260200160405180910390a250505050565b610db582825a613a61565b60408051610100810182525f60208083018281529383018281526060808501848152608080870186815260a080890188815260c08a0198895260e08a018690528a8a52968b015160d090811c909a5260268b015190955260468a0151909252606689015190921c9052607a87015190951c9091529284015190529082015160a283019060f01c806001600160401b03811115612e7657612e76614264565b604051908082528060200260200182016040528015612ebf57816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181612e945790505b50835160c001525f5b8161ffff16811015612f3e5760408051606080820183525f80835260208301818152938301908152865190911c8252601486015160d01c909252601a850151909152603a8401855160c00151805184908110612f2657612f2661525a565b60209081029190910101919091529250600101612ec8565b505050919050565b604082015160c082015151905f90819060010165ffffffffffff1683612f7f5760405163c2e5347d60e01b815260040160405180910390fd5b845165ffffffffffff16811015612fa9576040516363db3a4160e01b815260040160405180910390fd5b845186515f1965ffffffffffff9283168701019450168310612fde5760405163677c56f160e01b815260040160405180910390fd5b80831015612fff5760405163181432e760e11b815260040160405180910390fd5b845f015165ffffffffffff1681039150509250925092565b5f7f000000000000000000000000a4e7bf2f4f27989aa0a6b7d692edd195048fd2506001600160a01b031661304d57505f610c38565b604051633326844b60e11b81526001600160a01b0384811660048301525f9182917f000000000000000000000000a4e7bf2f4f27989aa0a6b7d692edd195048fd250169063664d0896906024016040805180830381865afa1580156130b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130d89190615537565b91509150805f036130ed575f92505050610c38565b8161313a577f000000000000000000000000000000000000000000000000000000000006978065ffffffffffff16841161313a5760405163c1a58f1960e01b815260040160405180910390fd5b506001949350505050565b5f6131ec7f00000000000000000000000000000000000000000000000000000000000000b460fc5f0160129054906101000a900465ffffffffffff160165ffffffffffff167f00000000000000000000000000000000000000000000000000000000000038408560c001518565ffffffffffff16815181106131c9576131c961525a565b6020026020010151602001510165ffffffffffff16613aa490919063ffffffff16565b90508042116131fa57505050565b6116f18360c001518365ffffffffffff168151811061321b5761321b61525a565b602090810291909101015151606085015161010191907f0000000000000000000000000000000000000000000000000000000000000000613ab9565b60c081015180515f919060096003820201836132838260408051828152600190920160051b8201905290565b6020808201529050855165ffffffffffff166040820152602086015160608201526040860151608082015260608601516001600160a01b031660a0820152608086015165ffffffffffff1660c082015260a086015160e082015260e0610100820152610120810183905260095f5b84811015613364575f86828151811061330c5761330c61525a565b602090810291909101015180516001600160a01b03166001850160051b8601529050602081015165ffffffffffff166002840160051b85015260408101516003840160051b85015250600391909101906001016132f1565b50815160051b602083012061338b8380516040516001820160051b83011490151060061b52565b979650505050505050565b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b6001600160a01b0382165f90815260208490526040902080546133e99083906001600160401b0316615563565b815467ffffffffffffffff19166001600160401b0391909116179055505050565b5f610c38633b9aca006001600160401b038416615582565b6040516001600160a01b038085166024830152831660448201526064810182905261141d9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613b76565b5f54610100900460ff16610de15760405162461bcd60e51b8152600401610d3d906152c0565b6001600160a01b0381163b6135205760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610d3d565b5f5160206155f85f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b61355783613c49565b5f825111806135635750805b156116f15761141d8383613c88565b5f8183116135805782610f0e565b50919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60408051808201909152606081525f60208201526101005460ff9065ffffffffffff80821691600160301b9004811690828203165f8061361883600a613572565b90505f5b818110156136995765ffffffffffff80871682015f9081526020899052604090206002810154909163010000009091041680158061367f57507f000000000000000000000000000000000000000000000000000000000000000061ffff16810142105b1561368b575050613699565b50506001928301920161361c565b50818810156136bb5760405163014b3fdb60e11b815260040160405180910390fd5b5f6136d1600a6136cb8b87613572565b90613572565b9050806001016001600160401b038111156136ee576136ee614264565b60405190808252806020026020018201604052801561375157816020015b61373e6040805180820182525f8082528251606080820185528152602081810183905293810191909152909182015290565b81526020019060019003908161370c5790505b508089525f906137669089908d908a86613cad565b5065ffffffffffff167f00000000000000000000000000000000000000000000000000000000000000a060ff167f000000000000000000000000000000000000000000000000000000000000000061ffff160201421160208a015250969998505050505050505050565b604080516060808201835281525f6020808301829052928201529082015161ffff1661380f5760405163fdac229f60e01b815260040160405180910390fd5b5f826020015161ffff166001600160401b0381111561383057613830614264565b604051908082528060200260200182016040528015613859578160200160208202803683370190505b5090505f5b836020015161ffff168110156138e157835161387f90829061ffff16615524565b498282815181106138925761389261525a565b6020026020010181815250508181815181106138b0576138b061525a565b60200260200101515f5f1b036138d957604051637bb2fa2f60e11b815260040160405180910390fd5b60010161385e565b50604080516060810182529182529283015162ffffff16602082015265ffffffffffff4216928101929092525090565b6001600160a01b0382165f90815260208490526040812080546001600160401b0380851691161080159061395357508054600160401b900465ffffffffffff16155b95945050505050565b61ffff811115610ca45760405163161e7a6b60e11b815260040160405180910390fd5b805160601b8252602081015160d01b60148301526040810151601a8301908152603a8301610f0e565b6001600160a01b0382165f90815260208490526040812080546001600160401b038085169116116139f357805467ffffffffffffffff19811682556001600160401b03169150613a29565b8054839250613a0c9083906001600160401b0316615505565b815467ffffffffffffffff19166001600160401b03919091161781555b509392505050565b6040516001600160a01b0383166024820152604481018290526116f190849063a9059cbb60e01b90606401613456565b815f03613a6d57505050565b613a8783838360405180602001604052805f815250613e2b565b6116f157604051634c67134d60e11b815260040160405180910390fd5b5f818311613ab25781610f0e565b5090919050565b5f613ac58585846139a8565b9050806001600160401b03165f03613add575061141d565b5f613ae9600283615599565b90505f613af68284615505565b90506001600160401b03821615613b1257613b128786846133bc565b604080516001600160401b038681168252848116602083015283168183015290516001600160a01b0387811692908916917faa22f5157944b5fa6846460e159d57ea9c3878e71fda274af372fa2ccf285aa09181900360600190a350505050505050565b5f613bca826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613e689092919063ffffffff16565b905080515f1480613bea575080806020019051810190613bea91906155c6565b6116f15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d3d565b613c52816134b3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610f0e838360405180606001604052806027815260200161561860279139613e7e565b5f5f825f03613cc6575065ffffffffffff905082613e21565b5f5f5b84811015613db65765ffffffffffff861681015f90815260208a815260409182902082518084018452600180825284519083018054608081870284018101909752606083018181529496939586019492939192849290918491840182828015613d4f57602002820191905f5260205f20905b815481526020019060010190808311613d3b575b50505091835250506001919091015462ffffff811660208301526301000000900465ffffffffffff1660409091015290528851899084908110613d9457613d9461525a565b6020908102919091010152546001600160401b03169190910190600101613cc9565b50613dd06001600160a01b038816633b9aca008302612dcd565b855f81518110613de257613de261525a565b602002602001015160200151604001519250838501915081886001015f6101000a81548165ffffffffffff021916908365ffffffffffff160217905550505b9550959350505050565b5f6001600160a01b038516613e5357604051634c67134d60e11b815260040160405180910390fd5b5f5f835160208501878988f195945050505050565b6060613e7684845f85613ef2565b949350505050565b60605f5f856001600160a01b031685604051613e9a91906155e1565b5f60405180830381855af49150503d805f8114613ed2576040519150601f19603f3d011682016040523d82523d5f602084013e613ed7565b606091505b5091509150613ee886838387613fba565b9695505050505050565b606082471015613f535760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610d3d565b5f5f866001600160a01b03168587604051613f6e91906155e1565b5f6040518083038185875af1925050503d805f8114613fa8576040519150601f19603f3d011682016040523d82523d5f602084013e613fad565b606091505b509150915061338b878383875b606083156140285782515f03614021576001600160a01b0385163b6140215760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d3d565b5081613e76565b613e76838381511561403d5781518083602001fd5b8060405162461bcd60e51b8152600401610d3d91906140dd565b6001600160a01b0381168114610ca4575f5ffd5b803561407681614057565b919050565b5f6020828403121561408b575f5ffd5b8135610f0e81614057565b5f60a08284031280156140a7575f5ffd5b509092915050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610f0e60208301846140af565b6001600160401b0381168114610ca4575f5ffd5b5f60208284031215614113575f5ffd5b8135610f0e816140ef565b65ffffffffffff81168114610ca4575f5ffd5b80356140768161411e565b5f5f6040838503121561414d575f5ffd5b82356141588161411e565b915060208301356141688161411e565b809150509250929050565b8051606080845281519084018190525f9160200190829060808601905b808310156141b35783518252602082019150602084019350600183019250614190565b5062ffffff602086015116602087015265ffffffffffff604086015116604087015280935050505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561425857603f1987860301845281516001600160401b03815116865260208101519050604060208701526142426040870182614173565b9550506020938401939190910190600101614207565b50929695505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b038111828210171561429a5761429a614264565b60405290565b604080519081016001600160401b038111828210171561429a5761429a614264565b60405161012081016001600160401b038111828210171561429a5761429a614264565b60405160c081016001600160401b038111828210171561429a5761429a614264565b60405160e081016001600160401b038111828210171561429a5761429a614264565b604051601f8201601f191681016001600160401b038111828210171561435157614351614264565b604052919050565b5f5f6040838503121561436a575f5ffd5b823561437581614057565b915060208301356001600160401b0381111561438f575f5ffd5b8301601f8101851361439f575f5ffd5b80356001600160401b038111156143b8576143b8614264565b6143cb601f8201601f1916602001614329565b8181528660208385010111156143df575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f6020828403121561440e575f5ffd5b5035919050565b5f5f83601f840112614425575f5ffd5b5081356001600160401b0381111561443b575f5ffd5b602083019150836020828501011115614452575f5ffd5b9250929050565b5f5f5f5f6040858703121561446c575f5ffd5b84356001600160401b03811115614481575f5ffd5b61448d87828801614415565b90955093505060208501356001600160401b038111156144ab575f5ffd5b6144b787828801614415565b95989497509550505050565b5f5f602083850312156144d4575f5ffd5b82356001600160401b038111156144e9575f5ffd5b6144f585828601614415565b90969095509350505050565b815165ffffffffffff16815260208083015160a08301916145489084018261ffff815116825261ffff602082015116602083015262ffffff60408201511660408301525050565b5061ffff604084015116608083015292915050565b5f6020828403121561456d575f5ffd5b81356001600160401b03811115614582575f5ffd5b82016101208185031215610f0e575f5ffd5b81516001600160a01b03168152610220810160208301516145c060208401826001600160a01b03169052565b5060408301516145db60408401826001600160a01b03169052565b5060608301516145f660608401826001600160a01b03169052565b50608083015161461160808401826001600160a01b03169052565b5060a083015161462c60a08401826001600160401b03169052565b5060c083015161464760c08401826001600160401b03169052565b5060e083015161466160e084018265ffffffffffff169052565b5061010083015161467d61010084018265ffffffffffff169052565b5061012083015161469961012084018265ffffffffffff169052565b506101408301516146b561014084018265ffffffffffff169052565b506101608301516146d161016084018265ffffffffffff169052565b506101808301516146e861018084018260ff169052565b506101a08301516147006101a084018261ffff169052565b506101c083015161471d6101c08401826001600160401b03169052565b506101e083015161473a6101e08401826001600160401b03169052565b5061020083015161475161020084018260ff169052565b5092915050565b5f60208284031215614768575f5ffd5b81356001600160401b0381111561477d575f5ffd5b820160208185031215610f0e575f5ffd5b5f5f6040838503121561479f575f5ffd5b82356147aa81614057565b91506020830135614168816140ef565b803561ffff81168114614076575f5ffd5b62ffffff81168114610ca4575f5ffd5b8035614076816147cb565b5f606082840312156147f6575f5ffd5b6147fe614278565b9050614809826147ba565b8152614817602083016147ba565b6020820152604082013561482a816147cb565b604082015292915050565b5f60608284031215614845575f5ffd5b610f0e83836147e6565b5f8151808452602084019350602083015f5b828110156148a957815180516001600160a01b0316875260208082015165ffffffffffff16818901526040918201519188019190915260609096019590910190600101614861565b5093949350505050565b602081525f825160208084015265ffffffffffff8151166040840152602081015160608401526040810151608084015260018060a01b0360608201511660a084015265ffffffffffff60808201511660c084015260a081015160e084015260c0810151905060e0610100840152613e7661012084018261484f565b5f6020828403121561493e575f5ffd5b81356001600160401b03811115614953575f5ffd5b820160e08185031215610f0e575f5ffd5b5f60a0828403128015614975575f5ffd5b5061497e614278565b82356149898161411e565b815261499884602085016147e6565b60208201526149a9608084016147ba565b60408201529392505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b80516140768161411e565b805161407681614057565b60ff81168114610ca4575f5ffd5b805161407681614a63565b5f6001600160401b03821115614a9457614a94614264565b5060051b60200190565b8015158114610ca4575f5ffd5b8051614076816147cb565b5f82601f830112614ac5575f5ffd5b8151614ad8614ad382614a7c565b614329565b8082825260208201915060208360051b860101925085831115614af9575f5ffd5b602085015b83811015614c3b5780516001600160401b03811115614b1b575f5ffd5b86016040818903601f19011215614b30575f5ffd5b614b386142a0565b6020820151614b4681614a9e565b815260408201516001600160401b03811115614b60575f5ffd5b6020818401019250506060828a031215614b78575f5ffd5b614b80614278565b82516001600160401b03811115614b95575f5ffd5b8301601f81018b13614ba5575f5ffd5b8051614bb3614ad382614a7c565b8082825260208201915060208360051b85010192508d831115614bd4575f5ffd5b6020840193505b82841015614bf6578351825260209384019390910190614bdb565b845250614c0891505060208401614aab565b6020820152614c1960408401614a4d565b6040820152806020830152508085525050602083019250602081019050614afe565b5095945050505050565b5f6101208284031215614c56575f5ffd5b614c5e6142c2565b9050614c6982614a4d565b8152614c7760208301614a4d565b6020820152614c8860408301614a4d565b6040820152614c9960608301614a58565b606082015260808281015190820152614cb460a08301614a4d565b60a082015260c08281015190820152614ccf60e08301614a71565b60e08201526101008201516001600160401b03811115614ced575f5ffd5b614cf984828501614ab6565b6101008301525092915050565b5f5f5f5f848603610120811215614d1b575f5ffd5b8551614d268161411e565b945060c0601f1982011215614d39575f5ffd5b50614d426142e5565b6020860151614d508161411e565b81526040860151614d608161411e565b60208201526060860151614d738161411e565b60408201526080860151614d868161411e565b606082015260a0860151614d998161411e565b608082015260c086015160a082015260e08601519093506001600160401b03811115614dc3575f5ffd5b614dcf87828801614c45565b61010096909601519497939650505050565b634e487b7160e01b5f52601260045260245ffd5b5f82614e0357614e03614de1565b500690565b803561407681614a63565b5f82601f830112614e22575f5ffd5b8135614e30614ad382614a7c565b8082825260208201915060208360051b860101925085831115614e51575f5ffd5b602085015b83811015614c3b5780356001600160401b03811115614e73575f5ffd5b86016040818903601f19011215614e88575f5ffd5b614e906142a0565b6020820135614e9e81614a9e565b815260408201356001600160401b03811115614eb8575f5ffd5b6020818401019250506060828a031215614ed0575f5ffd5b614ed8614278565b82356001600160401b03811115614eed575f5ffd5b8301601f81018b13614efd575f5ffd5b8035614f0b614ad382614a7c565b8082825260208201915060208360051b85010192508d831115614f2c575f5ffd5b6020840193505b82841015614f4e578335825260209384019390910190614f33565b845250614f60915050602084016147db565b6020820152614f7160408401614131565b6040820152806020830152508085525050602083019250602081019050614e56565b5f6101208236031215614fa4575f5ffd5b614fac6142c2565b614fb583614131565b8152614fc360208401614131565b6020820152614fd460408401614131565b6040820152614fe56060840161406b565b60608201526080838101359082015261500060a08401614131565b60a082015260c0838101359082015261501b60e08401614e08565b60e08201526101008301356001600160401b03811115615039575f5ffd5b614cf936828601614e13565b5f82601f830112615054575f5ffd5b8135615062614ad382614a7c565b80828252602082019150602060608402860101925085831115615083575f5ffd5b602085015b83811015614c3b576060818803121561509f575f5ffd5b6150a7614278565b81356150b281614057565b815260208201356150c28161411e565b602082810191909152604083810135908301529084529290920191606001615088565b5f60e082840312156150f5575f5ffd5b6150fd614307565b905061510882614131565b8152602082810135908201526040808301359082015261512a6060830161406b565b606082015261513b60808301614131565b608082015260a0828101359082015260c08201356001600160401b03811115615162575f5ffd5b61516e84828501615045565b60c08301525092915050565b5f6020823603121561518a575f5ffd5b604051602081016001600160401b03811182821017156151ac576151ac614264565b60405282356001600160401b038111156151c4575f5ffd5b6151d0368286016150e5565b82525092915050565b8481526001600160401b0384811660208301528316604082015260c08101613953606083018461ffff815116825261ffff602082015116602083015262ffffff60408201511660408301525050565b5f60208284031215615238575f5ffd5b5051919050565b5f6020828403121561524f575f5ffd5b8151610f0e816140ef565b634e487b7160e01b5f52603260045260245ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b848152836020820152606060408201525f613ee860608301848661526e565b5f610c3836836150e5565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f65ffffffffffff83168061532257615322614de1565b8065ffffffffffff84160691505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561539d57601f19858403018852815180511515845260208101519050604060208501526153866040850182614173565b6020998a0199909450929092019150600101615352565b50909695505050505050565b84815265ffffffffffff8416602082015260ff83166040820152608060608201525f613ee86080830184615336565b6001600160a01b03841681526040602082018190525f90613953908301848661526e565b5f6020828403121561540c575f5ffd5b8151610f0e8161411e565b6020815261543060208201835165ffffffffffff169052565b5f602083015161544a604084018265ffffffffffff169052565b50604083015165ffffffffffff811660608401525060608301516001600160a01b038116608084015250608083015160a083015260a083015161549760c084018265ffffffffffff169052565b5060c083015160e083015260e08301516154b761010084018260ff169052565b5061010083015161012080840152613e76610140840182615336565b634e487b7160e01b5f52601160045260245ffd5b65ffffffffffff8181168382160190811115610c3857610c386154d3565b6001600160401b038281168282160390811115610c3857610c386154d3565b80820180821115610c3857610c386154d3565b5f5f60408385031215615548575f5ffd5b825161555381614a9e565b6020939093015192949293505050565b6001600160401b038181168382160190811115610c3857610c386154d3565b8082028115828204841417610c3857610c386154d3565b5f6001600160401b038316806155b1576155b1614de1565b806001600160401b0384160491505092915050565b5f602082840312156155d6575f5ffd5b8151610f0e81614a9e565b5f82518060208501845e5f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220d51ec19498c6238096cd20d98216f63ecca74c5a280a1ce7597db8e00f005efa64736f6c634300081e0033