Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- EtnaInbox
- Optimization enabled
- true
- Compiler version
- v0.8.30+commit.73712a01
- Optimization runs
- 200
- EVM Version
- prague
- Verified at
- 2026-10-12T09:09:02.271237Z
Constructor Arguments
0x000000000000000000000000044c2e53e9edddd1353a9d923fa39c1fa821e88e0000000000000000000000009a3a019b2820ae3d396120fb9b2782d37be4799c000000000000000000000000b261c6facc0707b674c7491338412fdf44733a4b0000000000000000000000000000000000000000000000000000000000028c590000000000000000000000000000000000000000000000000000000000000080
contracts/layer1/etna/impl/EtnaInbox.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { IEtnaInbox } from "../iface/IEtnaInbox.sol";
import { IEtnaStakingRegistry } from "../iface/IEtnaStakingRegistry.sol";
import { IProofVerifier } from "src/layer1/verifiers/IProofVerifier.sol";
import { EssentialContract } from "src/shared/common/EssentialContract.sol";
import { ICheckpointStore } from "src/shared/signal/ICheckpointStore.sol";
import { ISignalService } from "src/shared/signal/ISignalService.sol";
import "./EtnaInbox_Layout.sol"; // DO NOT DELETE
/// @title EtnaInbox
/// @notice The L1 anchor of an Etna PoS chain starting at L2 block 0. A fresh proxy records its
/// genesis checkpoint and initial committee in one initialization, then lands proven batches.
/// @dev Uses the existing ABCI storage interface without any Shasta state or migration logic.
/// Slots 251–257, 259–267 and 275–277 are reserved to keep the node-facing slots unchanged.
/// @custom:security-contact security@taiko.xyz
contract EtnaInbox is IEtnaInbox, EssentialContract {
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @dev The V5 statement in wire order. All fields are static, so abi.encode of this
/// memory-only struct is the same fifteen-word encoding as the flat field list. Building
/// it one field at a time keeps the non-IR compiler within its stack limit.
struct LandStatement {
bytes32 domain;
uint256 l1ChainId;
uint64 l2ChainId;
address inbox;
address stakingRegistry;
uint64 generation;
uint64 parentHeight;
bytes32 parentHash;
bytes32 committeeConfigHash;
uint64 lastHeight;
bytes32 lastBlockHash;
bytes32 lastStateRoot;
uint64 l1ReferenceBlockNumber;
bytes32 l1ReferenceBlockHash;
bytes32 blobHashesHash;
}
// ---------------------------------------------------------------
// Constants
// ---------------------------------------------------------------
/// @dev The initialized status value expected by the ABCI node.
uint8 private constant _ETNA_ACTIVE = 3;
/// @dev The smallest epoch length in L2 blocks.
uint64 private constant _MIN_EPOCH_LEN_L2 = 3;
/// @dev The domain tag of the landing statement.
bytes32 private constant _LAND_STATEMENT_TAG = bytes32("TAIKO_ETNA_LAND_V5");
/// @dev The number of most recent L1 blocks whose hash `blockhash` returns.
uint256 private constant _BLOCKHASH_WINDOW = 256;
/// @dev The EIP-2935 history storage contract.
address private constant _HISTORY_STORAGE_ADDRESS = 0x0000F90827F1C53a10cb7A02335B175320002935;
/// @dev The number of most recent L1 blocks whose hash the EIP-2935 contract serves.
uint256 private constant _HISTORY_SERVE_WINDOW = 8191;
// ---------------------------------------------------------------
// Immutable Variables
// ---------------------------------------------------------------
/// @dev The verifier of `land` proofs.
IProofVerifier internal immutable _proofVerifier;
/// @dev The L1 signal service that stores the L2 checkpoints.
ISignalService internal immutable _signalService;
/// @dev The Etna staking registry.
IEtnaStakingRegistry internal immutable _stakingRegistry;
/// @dev The chain id of the Etna L2.
uint64 internal immutable _l2ChainId;
/// @dev The maximum number of L2 blocks one `land` call may cover.
uint64 internal immutable _maxBatchBlocks;
// ---------------------------------------------------------------
// State Variables
// ---------------------------------------------------------------
/// @dev Slots 251–257: reserved to preserve the existing ABCI storage interface.
uint256[7] private __reservedBeforeStatus;
/// @dev Slot 258: 3 once initialized; zero before initialization.
uint8 private _status;
/// @dev Slots 259–267: reserved to preserve the ABCI storage interface.
uint256[9] private __reservedSpec;
/// @dev Slot 268: the recovery generation (bits 0–63; the rest is reserved for GOV-04).
uint64 private _recoveryGeneration;
/// @dev Slot 269: the authenticated parent-anchor committee derivation configuration.
bytes32 private _committeeConfigHash;
/// @dev Slots 270–271: the latest landed L2 block.
LandedCheckpoint private _lastCheckpoint;
/// @dev Slots 272–274: the genesis record at the existing activation-record slots.
Activation private _activation;
/// @dev Slots 275–277: reserved (#22262 publication register).
uint256[3] private __reservedPublications;
/// @dev Slot 278: the genesis committee record commitment; no future epoch mapping.
bytes32 private _genesisCommitteeRecordHash;
/// @dev Slot 279: the L1 block of the epoch-0 committee snapshot.
uint64 private _genesisCutoff;
uint256[21] private __gap;
// ---------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------
/// @notice Sets the implementation's immutable parameters.
/// @param _config The configuration; addresses, `l2ChainId` and `maxBatchBlocks` must be
/// non-zero.
constructor(Config memory _config) {
require(_config.proofVerifier != address(0), ZERO_ADDRESS());
require(_config.signalService != address(0), ZERO_ADDRESS());
require(_config.stakingRegistry != address(0), ZERO_ADDRESS());
require(_config.l2ChainId != 0, ZERO_VALUE());
require(_config.maxBatchBlocks != 0, ZERO_VALUE());
_proofVerifier = IProofVerifier(_config.proofVerifier);
_signalService = ISignalService(_config.signalService);
_stakingRegistry = IEtnaStakingRegistry(_config.stakingRegistry);
_l2ChainId = _config.l2ChainId;
_maxBatchBlocks = _config.maxBatchBlocks;
}
// ---------------------------------------------------------------
// External & Public Functions
// ---------------------------------------------------------------
/// @inheritdoc IEtnaInbox
function init(address _owner, GenesisParams calldata _params) external initializer {
require(_params.genesisBlockHash != 0 && _params.genesisStateRoot != 0, InvalidGenesis());
require(
_params.epochLenL2 >= _MIN_EPOCH_LEN_L2 && _params.epochLenL1 != 0, InvalidEpochLength()
);
require(_isValidGenesisCutoff(_params.genesisCutoff), InvalidGenesisCutoff());
require(_params.committeeRecordHash != 0, ZeroCommitteeRecord());
require(_params.committeeConfigHash != 0, ZeroCommitteeConfigHash());
__Essential_init(_owner);
uint64 l1Block = uint64(block.number);
_status = _ETNA_ACTIVE;
_activation = Activation({
genesisHeight: 0,
l1Block: l1Block,
epochLenL2: _params.epochLenL2,
epochLenL1: _params.epochLenL1,
genesisBlockHash: _params.genesisBlockHash,
genesisStateRoot: _params.genesisStateRoot
});
_genesisCutoff = _params.genesisCutoff;
_genesisCommitteeRecordHash = _params.committeeRecordHash;
_committeeConfigHash = _params.committeeConfigHash;
_lastCheckpoint = LandedCheckpoint({ height: 0, blockHash: _params.genesisBlockHash });
_signalService.saveCheckpoint(
ICheckpointStore.Checkpoint({
blockNumber: 0,
blockHash: _params.genesisBlockHash,
stateRoot: _params.genesisStateRoot
})
);
emit EtnaInitialized(
_params.genesisBlockHash,
_params.genesisStateRoot,
l1Block,
_params.epochLenL2,
_params.epochLenL1,
_params.genesisCutoff,
_params.committeeRecordHash
);
}
/// @inheritdoc IEtnaInbox
function land(LandInput calldata _input, bytes calldata _proof) external nonReentrant {
require(_status == _ETNA_ACTIVE, EtnaNotActive());
LandedCheckpoint memory parent = _lastCheckpoint;
uint64 lastHeight = _input.lastHeight;
require(lastHeight > parent.height, NoProgress());
require(lastHeight - parent.height <= _maxBatchBlocks, BatchTooLarge());
require(lastHeight <= type(uint48).max, HeightOverflow());
bytes32 statementHash = _hashLandStatement(
_recoveryGeneration,
parent.height,
parent.blockHash,
_input,
_readL1ReferenceBlockHash(_input.l1ReferenceBlockNumber),
_readBlobHashes()
);
_lastCheckpoint = LandedCheckpoint({ height: lastHeight, blockHash: _input.lastBlockHash });
_signalService.saveCheckpoint(
ICheckpointStore.Checkpoint({
blockNumber: uint48(lastHeight),
blockHash: _input.lastBlockHash,
stateRoot: _input.lastStateRoot
})
);
emit BatchLanded(
parent.height + 1,
lastHeight,
_input.lastBlockHash,
_input.lastStateRoot,
_input.l1ReferenceBlockNumber,
statementHash,
msg.sender
);
_proofVerifier.verifyProof(0, statementHash, _proof);
}
/// @inheritdoc IEtnaInbox
function hashLandStatement(
uint64 _generation,
uint64 _parentHeight,
bytes32 _parentHash,
LandInput calldata _input,
bytes32 _l1ReferenceBlockHash,
bytes32[] calldata _blobHashes
)
external
view
returns (bytes32 statementHash_)
{
return _hashLandStatement(
_generation, _parentHeight, _parentHash, _input, _l1ReferenceBlockHash, _blobHashes
);
}
/// @inheritdoc IEtnaInbox
function lastCheckpoint() external view returns (LandedCheckpoint memory) {
return _lastCheckpoint;
}
/// @inheritdoc IEtnaInbox
function committeeConfigHash() external view returns (bytes32 configHash_) {
return _committeeConfigHash;
}
/// @inheritdoc IEtnaInbox
function genesisCommitteeRecordHash() external view returns (bytes32 recordHash_) {
return _genesisCommitteeRecordHash;
}
/// @inheritdoc IEtnaInbox
function activation() external view returns (Activation memory) {
return _activation;
}
/// @inheritdoc IEtnaInbox
function genesisCutoff() external view returns (uint64) {
return _genesisCutoff;
}
/// @inheritdoc IEtnaInbox
function migrationState() external view returns (uint8) {
return _status;
}
/// @inheritdoc IEtnaInbox
function recoveryGeneration() external view returns (uint64) {
return _recoveryGeneration;
}
// ---------------------------------------------------------------
// Internal Functions
// ---------------------------------------------------------------
/// @dev Computes the landing statement hash; the single encoding behind `land` and
/// `hashLandStatement`. The execution address is the Inbox proxy under delegatecall, and
/// the registry address comes from this implementation's immutable configuration. The guest
/// and the lander reproduce this encoding byte for byte.
/// @param _generation The recovery generation.
/// @param _parentHeight The height of the block the batch builds on.
/// @param _parentHash The hash of the block the batch builds on.
/// @param _input The batch.
/// @param _l1ReferenceBlockHash The L1 block hash of `_input.l1ReferenceBlockNumber`.
/// @param _blobHashes The versioned hashes of the batch's blobs.
/// @return The landing statement hash.
function _hashLandStatement(
uint64 _generation,
uint64 _parentHeight,
bytes32 _parentHash,
LandInput calldata _input,
bytes32 _l1ReferenceBlockHash,
bytes32[] memory _blobHashes
)
internal
view
returns (bytes32)
{
LandStatement memory statement;
statement.domain = _LAND_STATEMENT_TAG;
statement.l1ChainId = block.chainid;
statement.l2ChainId = _l2ChainId;
statement.inbox = address(this);
statement.stakingRegistry = address(_stakingRegistry);
statement.generation = _generation;
statement.parentHeight = _parentHeight;
statement.parentHash = _parentHash;
statement.committeeConfigHash = _committeeConfigHash;
statement.lastHeight = _input.lastHeight;
statement.lastBlockHash = _input.lastBlockHash;
statement.lastStateRoot = _input.lastStateRoot;
statement.l1ReferenceBlockNumber = _input.l1ReferenceBlockNumber;
statement.l1ReferenceBlockHash = _l1ReferenceBlockHash;
statement.blobHashesHash = keccak256(abi.encodePacked(_blobHashes));
return keccak256(abi.encode(statement));
}
// ---------------------------------------------------------------
// Private Functions
// ---------------------------------------------------------------
/// @dev Returns the hash of L1 block `_l1ReferenceBlockNumber`: from `blockhash` for the last 256
/// blocks, from the EIP-2935 history contract for the last 8191; reverts otherwise or if the
/// hash is zero.
/// @param _l1ReferenceBlockNumber The L1 block number.
/// @return l1ReferenceBlockHash_ The L1 block hash.
function _readL1ReferenceBlockHash(uint64 _l1ReferenceBlockNumber)
private
view
returns (bytes32 l1ReferenceBlockHash_)
{
require(_l1ReferenceBlockNumber < block.number, AnchorUnavailable());
uint256 age = block.number - _l1ReferenceBlockNumber;
if (age <= _BLOCKHASH_WINDOW) {
l1ReferenceBlockHash_ = blockhash(_l1ReferenceBlockNumber);
} else {
require(age <= _HISTORY_SERVE_WINDOW, AnchorUnavailable());
(bool success, bytes memory data) =
_HISTORY_STORAGE_ADDRESS.staticcall(abi.encode(uint256(_l1ReferenceBlockNumber)));
require(success && data.length == 32, AnchorUnavailable());
l1ReferenceBlockHash_ = abi.decode(data, (bytes32));
}
require(l1ReferenceBlockHash_ != 0, AnchorUnavailable());
}
/// @dev Returns the versioned hashes of the transaction's blobs; reverts if there are none.
/// @return blobHashes_ `blobhash(0)`, `blobhash(1)`, ... up to the first zero.
function _readBlobHashes() private view returns (bytes32[] memory blobHashes_) {
uint256 count;
while (blobhash(count) != 0) {
++count;
}
require(count != 0, BlobsRequired());
blobHashes_ = new bytes32[](count);
for (uint256 i; i < count; ++i) {
blobHashes_[i] = blobhash(i);
}
}
/// @dev Returns whether `_cutoff` is a past L1 block at or after the registry's first
/// checkpoint, so the epoch-0 snapshot exists.
/// @param _cutoff The genesis cutoff.
/// @return Whether the cutoff is valid.
function _isValidGenesisCutoff(uint64 _cutoff) private view returns (bool) {
if (_cutoff >= block.number) return false;
if (_stakingRegistry.checkpointCount() == 0) return false;
return _stakingRegistry.checkpointAt(0).l1Block <= _cutoff;
}
// ---------------------------------------------------------------
// Custom Errors
// ---------------------------------------------------------------
error AnchorUnavailable();
error BatchTooLarge();
error BlobsRequired();
error EtnaNotActive();
error InvalidGenesis();
error HeightOverflow();
error InvalidEpochLength();
error InvalidGenesisCutoff();
error NoProgress();
error ZeroCommitteeRecord();
error ZeroCommitteeConfigHash();
}
contracts/layer1/etna/iface/IEtnaInbox.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/// @title IEtnaInbox
/// @notice The L1 anchor of an Etna PoS chain that starts from L2 genesis.
/// @dev A fresh proxy is initialized with the L2 block-0 hash and state root, epoch parameters,
/// and the initial committee record and derivation configuration hash. The node authenticates
/// genesis and checkpoint storage with EIP-1186 proofs. Future committees derive from the
/// committed switch-parent anchor and are never published by landing transactions.
/// @custom:security-contact security@taiko.xyz
interface IEtnaInbox {
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @notice The constructor parameters of the Etna Inbox implementation.
struct Config {
/// @notice The verifier of `land` proofs.
address proofVerifier;
/// @notice The L1 signal service that stores the L2 checkpoints.
address signalService;
/// @notice The Etna staking registry the committees derive from.
address stakingRegistry;
/// @notice The chain id of the Etna L2.
uint64 l2ChainId;
/// @notice The maximum number of L2 blocks one `land` call may cover.
uint64 maxBatchBlocks;
}
/// @notice The genesis parameters of a new Etna chain.
struct GenesisParams {
/// @notice The hash of L2 block 0.
bytes32 genesisBlockHash;
/// @notice The state root of L2 block 0.
bytes32 genesisStateRoot;
/// @notice The epoch length in L2 blocks.
uint64 epochLenL2;
/// @notice The epoch length in L1 blocks.
uint64 epochLenL1;
/// @notice A past L1 block whose registry snapshot defines committee 0.
uint64 genesisCutoff;
/// @notice The initial committee record hash, computed from that snapshot.
bytes32 committeeRecordHash;
/// @notice The non-zero commitment to the parent-anchor committee derivation configuration.
bytes32 committeeConfigHash;
}
/// @notice The genesis record; named activation for the existing node storage interface.
/// @dev Three storage words: `genesisHeight` (bits 0–63), `l1Block` (bits 64–127),
/// `epochLenL2` (bits 128–191) and `epochLenL1` (bits 192–255), then `genesisBlockHash`, then
/// `genesisStateRoot`.
struct Activation {
/// @notice The Etna genesis height, always 0.
uint64 genesisHeight;
/// @notice `L1_0`: the L1 block in which the proxy was initialized.
uint64 l1Block;
/// @notice `L`: the epoch length in L2 blocks.
uint64 epochLenL2;
/// @notice The epoch length in L1 blocks.
uint64 epochLenL1;
/// @notice `H*`: the block hash of `B*`.
bytes32 genesisBlockHash;
/// @notice `S*`: the state root of `B*`.
bytes32 genesisStateRoot;
}
/// @notice The latest L2 block landed on L1 (block 0 after initialization).
/// @dev Two storage words: `height` (bits 0–63), then `blockHash`.
struct LandedCheckpoint {
/// @notice The L2 block height.
uint64 height;
/// @notice The L2 block hash.
bytes32 blockHash;
}
/// @notice The batch of `land`: the L2 blocks after the last checkpoint up to `lastHeight`.
struct LandInput {
/// @notice The height of the batch's last block.
uint64 lastHeight;
/// @notice The hash of the batch's last block.
bytes32 lastBlockHash;
/// @notice The state root of the batch's last block.
bytes32 lastStateRoot;
/// @notice The L1 reference block authenticating the batch's anchor header chain.
/// @dev Every L2 block may have its own anchor; all must be on the L1 header chain ending
/// at this reference block, whose number is at least the last block's anchor number.
/// A lander picks a recent L1 block, so a landing outage longer than the EIP-2935
/// window does not strand the batch.
uint64 l1ReferenceBlockNumber;
}
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
/// @notice Emitted when a fresh Etna proxy is initialized from L2 genesis.
/// @param genesisBlockHash The hash of L2 block 0.
/// @param genesisStateRoot The state root of L2 block 0.
/// @param l1Block The L1 initialization block.
/// @param epochLenL2 The epoch length in L2 blocks.
/// @param epochLenL1 The epoch length in L1 blocks.
/// @param genesisCutoff The initial committee's registry snapshot block.
/// @param committeeRecordHash The initial committee record hash.
event EtnaInitialized(
bytes32 genesisBlockHash,
bytes32 genesisStateRoot,
uint64 l1Block,
uint64 epochLenL2,
uint64 epochLenL1,
uint64 genesisCutoff,
bytes32 committeeRecordHash
);
/// @notice Emitted when a batch is landed.
/// @param firstHeight The height of the batch's first block.
/// @param lastHeight The height of the batch's last block, the new checkpoint.
/// @param lastBlockHash The hash of the batch's last block.
/// @param lastStateRoot The state root of the batch's last block.
/// @param l1ReferenceBlockNumber The L1 block whose header chain holds every block's anchor.
/// @param statementHash The landing statement hash the proof was verified against.
/// @param lander The caller.
event BatchLanded(
uint64 firstHeight,
uint64 lastHeight,
bytes32 lastBlockHash,
bytes32 lastStateRoot,
uint64 l1ReferenceBlockNumber,
bytes32 statementHash,
address indexed lander
);
// ---------------------------------------------------------------
// External Functions
// ---------------------------------------------------------------
/// @notice Initializes a fresh Etna proxy and its L2 block-0 checkpoint.
/// @dev Call atomically in the proxy constructor. Requires non-zero genesis hash, state root,
/// committee record and derivation configuration hash, epochLenL2 >= 3, epochLenL1 > 0, and
/// a past genesis cutoff at or after the registry's first checkpoint. The SignalService must
/// authorize this proxy as its
/// syncer: initialization saves its block-0 checkpoint too, and any failure rolls back all
/// state. The owner supplies the trusted genesis values and the committee record computed
/// from the registry snapshot. The node also requires L >= D_MAX - MARGIN_V + 3.
/// @param _owner The owner; the proxy deployer if zero.
/// @param _params The genesis parameters.
function init(address _owner, GenesisParams calldata _params) external;
/// @notice Lands the L2 blocks after the last checkpoint up to `_input.lastHeight`.
/// @dev Permissionless. Requires active status, progress, at most `maxBatchBlocks` blocks,
/// and a last height at or below `type(uint48).max`. The reference is a past L1 block with
/// a non-zero hash available through blockhash (256 blocks) or EIP-2935 (8191 blocks).
/// At least one blob is required, and every actual transaction blob hash is bound in order.
/// Saves the terminal checkpoint in the Inbox and SignalService, emits BatchLanded, then
/// verifies the V5 statement with proposal age 0; verifier failure rolls back every write.
/// No future committee record is an input or output of landing.
///
/// A valid Etna proof must authenticate every Inbox/registry account and storage proof under
/// the respective bound address and authenticated L1 state root. It must open the stored
/// committeeConfigHash using the exact nine-word encoding (288 bytes):
/// abi.encode(bytes32("ETNA_PARENT_ANCHOR_V1"), uint256(l2ChainId), address(stakingRegistry),
/// uint256(vpUnit), uint256(sMin), uint64(nMax), uint64(heartbeatWindow), uint64(2), uint8(1)).
/// The final words bind heartbeat lookahead 2 and retained membership algorithm version 1.
/// Authenticate the genesis schedule and explicit genesisCutoff from Inbox storage.
/// Committee 0 opens the plain slot-278 bootstrap record at genesisCutoff (slot 279).
///
/// For t >= 1, H(t) = 1 + t * epochLenL2, S(t) = H(t) - 2 and D(t) = H(t) - 3, with
/// checked arithmetic. At S(t), derive the incoming set at exactly the committed parent's
/// anchor number, under that parent's authenticated L1 root; never the candidate's anchor.
/// Authenticate complete registry entries/count/root and evaluate active/exit eligibility at
/// that snapshot number. Preserve effective stake, earliest eligible bondId per pubkey,
/// nMax ranking, MEM-08 ordering/root, voting-power division and overflow caps. Heartbeats
/// retain target-epoch evaluation with lookahead 2 and exemptions for epochs 0, 1 and 2.
/// Non-switch blocks forbid runtime committee witnesses. No empty-set fallback is implied.
///
/// For arbitrary batch starts, authenticate the checkpoint EL header against the public
/// parent hash, then consecutive descending parentHash links through each required D(t).
/// Read the snapshot number only from D(t)'s generation-checked Etna anchor extraData;
/// a separate derivation hint or the checkpoint's newer anchor cannot select the set.
/// At nonzero checkpoint heights also authenticate the preceding EL header for the base-fee
/// grandparent timestamp. Current/next starting epochs differ by at most one; checked
/// history bounds require at most epochLenL2 + 2 links, without replaying old transactions.
/// A later authenticated proving root whose number covers the snapshot may prove the last
/// immutable registry checkpoint at/before it, the successor after it (when present), array
/// length and complete entries/root. Recompute all parent/current/pending sets. In-batch
/// switches still require the actual committed parent's exact root and snapshot number.
///
/// Apply CometBFT H+2 timing: updates returned at S(t) and persisted at Commit activate at
/// H(t). Verify the parent certificate, every current/pending certificate and current/next
/// validator hash across S/S+1/H and arbitrary cuts, with strictly more than 2/3 distinct
/// signer voting power under taiko-etna-<l2ChainId>-g<generation>. Anchor progress, status,
/// generation and back-pressure rules still apply; deterministic Finalize/replay makes no
/// new L1 calls. Epoch-first blocks need no publication witness.
///
/// Prove contiguous execution from the parent hash to the terminal hash/state root, every
/// anchor and actual proving L1 root on the header chain ending at the reference hash, and
/// block data in the bound blobs. A batch may start/end at any valid height without a previous
/// batch's committee output. Envelope version 3 and journal schema 3 reject former V2/V4
/// histories/jobs; never discard or replace a signed nonce. The verifier must pin a guest
/// enforcing these V5 rules. Dummy proof 0x00 is for development only; no real guest exists
/// here and the dummy verifier does not establish consensus validity or ZK soundness.
/// @param _input The four-field batch terminal checkpoint and reference block.
/// @param _proof The proof of the V5 landing statement.
function land(LandInput calldata _input, bytes calldata _proof) external;
/// @notice Encodes the V5 landing statement for supplied batch public inputs.
/// @dev Fifteen static ABI words (480 bytes): bytes32("TAIKO_ETNA_LAND_V5"), block.chainid,
/// l2ChainId, address(this), address(stakingRegistry), _generation, _parentHeight, _parentHash,
/// committeeConfigHash, lastHeight, lastBlockHash, lastStateRoot, l1ReferenceBlockNumber,
/// _l1ReferenceBlockHash, keccak256(abi.encodePacked(_blobHashes)). Chain id is uint256;
/// generation/heights are uint64, identities address and hashes bytes32. Identities and the
/// config hash are read internally; call through the Inbox proxy to bind its address.
/// This helper does not authenticate supplied batch values. land reads the stored parent
/// and generation, resolves the reference hash and reads the actual transaction blob hashes.
/// @param _generation The recovery generation.
/// @param _parentHeight The parent checkpoint height.
/// @param _parentHash The parent checkpoint block hash.
/// @param _input The four-field batch.
/// @param _l1ReferenceBlockHash The hash of `_input.l1ReferenceBlockNumber`.
/// @param _blobHashes The versioned blob hashes in transaction order.
/// @return statementHash_ The V5 statement hash.
function hashLandStatement(
uint64 _generation,
uint64 _parentHeight,
bytes32 _parentHash,
LandInput calldata _input,
bytes32 _l1ReferenceBlockHash,
bytes32[] calldata _blobHashes
)
external
view
returns (bytes32 statementHash_);
/// @notice Returns the latest landed L2 block.
/// @dev The initialized checkpoint is L2 block 0.
/// @return The latest landed checkpoint; zero before initialization.
function lastCheckpoint() external view returns (LandedCheckpoint memory);
/// @notice Returns the authenticated committee derivation configuration commitment.
/// @dev Stored at slot 269; installed once from the trusted genesis deployment input.
/// @return configHash_ The configuration hash; zero before initialization.
function committeeConfigHash() external view returns (bytes32 configHash_);
/// @notice Returns the initial committee record commitment.
/// @dev Stored directly at slot 278; no future epoch committee mapping exists.
/// @return recordHash_ The genesis committee record hash; zero before initialization.
function genesisCommitteeRecordHash() external view returns (bytes32 recordHash_);
/// @notice Returns the genesis record at the existing activation-record slots.
/// @dev The schedule and hashes are installed once during initialization.
/// @return The genesis record; zero before initialization.
function activation() external view returns (Activation memory);
/// @notice Returns the L1 block of the epoch-0 committee snapshot.
/// @dev Committee 0 alone uses this explicit snapshot; runtime sets use switch-parent anchors.
/// @return The genesis cutoff; zero before initialization.
function genesisCutoff() external view returns (uint64);
/// @notice Returns the status word consumed by the existing ABCI node.
/// @dev The name is retained for node compatibility; there is no migration state machine.
/// @return 3 after initialization, 0 before initialization.
function migrationState() external view returns (uint8);
/// @notice Returns the recovery generation bound into every landing statement.
/// @dev Stays 0 until stall recovery (GOV-04) exists.
/// @return The recovery generation.
function recoveryGeneration() external view returns (uint64);
}
contracts/layer1/etna/iface/IEtnaStakingRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/// @title IEtnaStakingRegistry
/// @notice The TAIKO staking registry the Etna PoS node derives its committees from.
/// @dev Validators register an Ed25519 consensus key with a TAIKO stake, heartbeat once per
/// heartbeat window, request an exit and withdraw after the withdrawal delay. Entries are
/// append-only and indexed by bond id. Every L1 block that changes an entry ends with one
/// checkpoint holding the entry count and the entries Merkle root at the end of that block.
///
/// The node reads `checkpoints` and `entries` straight from storage with EIP-1186 proofs, so the
/// field order and packing of both structs, and their ERC-7201 location, are part of the
/// node-facing layout (taiko-client-rs `crates/abci/src/l1/layout.rs`).
/// @custom:security-contact security@taiko.xyz
interface IEtnaStakingRegistry {
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @notice The registry as it stands at the end of one L1 block that changed an entry.
/// @dev Two storage words: `l1Block` (bits 0–63) and `count` (bits 64–95), then
/// `entriesRoot`.
struct Checkpoint {
/// @notice The L1 block whose entry changes this checkpoint captures.
uint64 l1Block;
/// @notice The number of entries (exited ones included) at the end of `l1Block`.
uint32 count;
/// @notice The entries Merkle root over the first `count` entries.
bytes32 entriesRoot;
}
/// @notice One registration, indexed by its bond id.
/// @dev Three storage words: `pubkey`, `effStake`, then `activeFromL1` (bits 0–63),
/// `exitEffectiveL1` (bits 64–127), `lastHeartbeatAt` (bits 128–191) and
/// `lastHeartbeatSeq` (bits 192–255).
struct Entry {
/// @notice The Ed25519 consensus public key.
bytes32 pubkey;
/// @notice The effective stake in TAIKO base units.
uint256 effStake;
/// @notice The first L1 block at which the entry may be selected.
uint64 activeFromL1;
/// @notice The L1 block at which the exit takes effect; `type(uint64).max` if none was
/// requested.
uint64 exitEffectiveL1;
/// @notice The start L1 block of the heartbeat window of the last accepted heartbeat
/// (MEM-13(2b)); 0 until the first heartbeat (registration is not one).
uint64 lastHeartbeatAt;
/// @notice The number of accepted heartbeats; 0 means none. A first heartbeat in window
/// 0 leaves `lastHeartbeatAt` at 0, so this, not `lastHeartbeatAt`, tells whether the
/// entry has a heartbeat (MEM-13(3)).
uint64 lastHeartbeatSeq;
}
// ---------------------------------------------------------------
// Events
// ---------------------------------------------------------------
/// @notice Emitted when a validator registers.
/// @param bondId The new entry's bond id.
/// @param owner The bond owner (the caller).
/// @param pubkey The Ed25519 consensus public key.
/// @param amount The TAIKO stake pulled from the owner.
/// @param activeFromL1 The first L1 block at which the entry may be selected.
event Registered(
uint256 indexed bondId,
address indexed owner,
bytes32 pubkey,
uint256 amount,
uint64 activeFromL1
);
/// @notice Emitted when a heartbeat is accepted.
/// @param bondId The entry's bond id.
/// @param windowStart The start L1 block of the heartbeat window, now the entry's
/// `lastHeartbeatAt`.
/// @param seq The entry's new `lastHeartbeatSeq`, the number of heartbeats accepted so far.
event HeartbeatRecorded(uint256 indexed bondId, uint64 windowStart, uint64 seq);
/// @notice Emitted when the bond owner requests an exit.
/// @param bondId The entry's bond id.
/// @param exitEffectiveL1 The L1 block at which the exit takes effect.
event ExitRequested(uint256 indexed bondId, uint64 exitEffectiveL1);
/// @notice Emitted when an exited entry's stake is withdrawn.
/// @param bondId The entry's bond id.
/// @param to The recipient of the stake.
/// @param amount The TAIKO amount transferred.
event StakeWithdrawn(uint256 indexed bondId, address indexed to, uint256 amount);
/// @notice Emitted when the current block's checkpoint is appended or overwritten.
/// @param index The checkpoint's index.
/// @param l1Block The L1 block the checkpoint captures (the current block).
/// @param count The number of entries at this point of the block.
/// @param entriesRoot The entries Merkle root at this point of the block.
event CheckpointWritten(
uint256 indexed index, uint64 l1Block, uint32 count, bytes32 entriesRoot
);
// ---------------------------------------------------------------
// External Functions
// ---------------------------------------------------------------
/// @notice Registers `_pubkey` with a stake of `_amount` TAIKO pulled from the caller, who
/// becomes the bond owner.
/// @dev Reverts if `_amount` is below the minimum stake, `_pubkey` is zero, the registry
/// holds `MAX_ENTRIES` entries, or another entry holds `_pubkey` and its exit is not yet
/// effective. The entry becomes active `activationDelay` blocks later, has no exit and no
/// heartbeat (`lastHeartbeatAt = 0`, `lastHeartbeatSeq = 0`). Writes the current block's
/// checkpoint.
/// @param _pubkey The Ed25519 consensus public key.
/// @param _amount The TAIKO stake; the caller must have approved it.
/// @return bondId_ The new entry's bond id (its index).
function register(bytes32 _pubkey, uint256 _amount) external returns (uint256 bondId_);
/// @notice Records a heartbeat for `_bondId` in the current heartbeat window.
/// @dev Only the bond owner, and only before the exit takes effect. With
/// `windowStart = floor(block.number / heartbeatWindow) * heartbeatWindow`, the heartbeat
/// is accepted if the entry has none yet (`lastHeartbeatSeq == 0`) or `windowStart` exceeds
/// `lastHeartbeatAt`: at most one heartbeat per window, and `lastHeartbeatAt` never
/// decreases. It then sets `lastHeartbeatAt = windowStart`, increments `lastHeartbeatSeq`
/// and writes the current block's checkpoint.
///
/// A first heartbeat in window 0 is valid and leaves `lastHeartbeatAt` at 0, so
/// `lastHeartbeatAt` alone cannot tell "heartbeat in window 0" from "no heartbeat". The
/// sequence is MEM-13(3)'s "has a heartbeat" guard: the node counts an entry as live only
/// if `lastHeartbeatSeq > 0 && lastHeartbeatAt >= floor`, where `floor` is the start of
/// the oldest window it still accepts.
///
/// The bond owner's address heartbeats directly; MEM-13's ECDSA heartbeat key and relayed
/// signed heartbeats are a follow-up.
/// @param _bondId The entry's bond id.
function heartbeat(uint256 _bondId) external;
/// @notice Requests the exit of `_bondId`.
/// @dev Only the bond owner, once. The exit takes effect at
/// `max(block.number, activeFromL1) + exitDelay`. Writes the current block's checkpoint.
/// @param _bondId The entry's bond id.
function requestExit(uint256 _bondId) external;
/// @notice Transfers the stake of `_bondId` to `_to`.
/// @dev Only the bond owner, once, and only from `exitEffectiveL1 + withdrawalDelay` on. The
/// entry itself is left unchanged, so no checkpoint is written.
/// @param _bondId The entry's bond id.
/// @param _to The recipient of the stake.
function withdraw(uint256 _bondId, address _to) external;
/// @notice Returns the number of checkpoints.
/// @return The number of checkpoints.
function checkpointCount() external view returns (uint256);
/// @notice Returns checkpoint `_index`; reverts if it does not exist.
/// @param _index The checkpoint index.
/// @return The checkpoint.
function checkpointAt(uint256 _index) external view returns (Checkpoint memory);
/// @notice Returns the number of entries (exited ones included), which is the next bond id.
/// @return The number of entries.
function entryCount() external view returns (uint256);
/// @notice Returns entry `_bondId`; reverts if it does not exist.
/// @param _bondId The bond id.
/// @return The entry.
function entryAt(uint256 _bondId) external view returns (Entry memory);
/// @notice Returns the entries Merkle root over all current entries.
/// @dev Equals the latest checkpoint's `entriesRoot` (`bytes32(0)` before the first entry).
/// @return The entries Merkle root.
function entriesRoot() external view returns (bytes32);
/// @notice Returns the owner of `_bondId`, or `address(0)` if it does not exist.
/// @param _bondId The bond id.
/// @return The bond owner.
function bondOwnerOf(uint256 _bondId) external view returns (address);
/// @notice Returns whether the stake of `_bondId` was withdrawn (false if it does not
/// exist).
/// @param _bondId The bond id.
/// @return Whether the stake was withdrawn.
function isWithdrawn(uint256 _bondId) external view returns (bool);
}
contracts/layer1/etna/impl/EtnaInbox_Layout.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/// @title EtnaInboxLayout
/// @notice Storage layout documentation for EtnaInbox
/// @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
// __reservedBeforeStatus | uint256[7] | Slot: 251 | Offset: 0 | Bytes: 224
// _status | uint8 | Slot: 258 | Offset: 0 | Bytes: 1
// __reservedSpec | uint256[9] | Slot: 259 | Offset: 0 | Bytes: 288
// _recoveryGeneration | uint64 | Slot: 268 | Offset: 0 | Bytes: 8
// _committeeConfigHash | bytes32 | Slot: 269 | Offset: 0 | Bytes: 32
// _lastCheckpoint | struct IEtnaInbox.LandedCheckpoint | Slot: 270 | Offset: 0 | Bytes: 64
// _activation | struct IEtnaInbox.Activation | Slot: 272 | Offset: 0 | Bytes: 96
// __reservedPublications | uint256[3] | Slot: 275 | Offset: 0 | Bytes: 96
// _genesisCommitteeRecordHash | bytes32 | Slot: 278 | Offset: 0 | Bytes: 32
// _genesisCutoff | uint64 | Slot: 279 | Offset: 0 | Bytes: 8
// __gap | uint256[21] | Slot: 280 | Offset: 0 | Bytes: 672
contracts/layer1/verifiers/IProofVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @title IProofVerifier
/// @notice Interface for verifying validity proofs for state transitions
/// @custom:security-contact security@taiko.xyz
interface IProofVerifier {
/// @notice Verifies a validity proof for a state transition
/// @dev This function must revert if the proof is invalid
/// @param _proposalAge The age in seconds of the proposal being proven. Only set for
/// single-proposal proofs (calculated as block.timestamp - proposal.timestamp).
/// For multi-proposal batches, this is always 0, meaning "not applicable".
/// Verifiers should interpret _proposalAge == 0 as "not applicable" rather than
/// "instant proof". This parameter enables age-based verification logic, such as
/// detecting and handling prover-killer proposals differently.
/// @param _commitmentHash Hash of the last proposal hash and commitment data
/// @param _proof The proof data
function verifyProof(
uint256 _proposalAge,
bytes32 _commitmentHash,
bytes calldata _proof
)
external
view;
}
contracts/shared/common/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;
/// @dev Transient-storage slot for the reentry lock: keccak256("ownerUUPS.reentry_slot") + 1.
/// The addition prevents collisions with EIP-1967-style slots (derived as keccak256(x) - 1)
/// and SignalService slots (derived directly as keccak256(x)).
bytes32 private constant _REENTRY_SLOT =
0xa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b;
address internal immutable __resolver;
// ---------------------------------------------------------------
// State Variables
// ---------------------------------------------------------------
uint256[50] private __gapFromOldAddressResolver;
/// @dev Slot 1. __reentry is deprecated: the reentry lock lives in transient storage
/// (_REENTRY_SLOT); the storage slot is retained only for layout compatibility.
uint8 private __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 in transient storage (EIP-1153). This is deliberately not virtual:
// L1 and L2 run the same EVM version, so the transient-storage lock is the single reentrancy
// guard implementation.
function _storeReentryLock(uint8 _reentry) internal {
assembly {
tstore(_REENTRY_SLOT, _reentry)
}
}
// Loads the reentry lock
function _loadReentryLock() internal view returns (uint8 reentry_) {
assembly {
reentry_ := tload(_REENTRY_SLOT)
}
}
// ---------------------------------------------------------------
// Private Functions
// ---------------------------------------------------------------
function _checkOwnerOr(address _addr) private view {
require(msg.sender == owner() || msg.sender == _addr, ACCESS_DENIED());
}
function _checkReentrancy() private view {
require(_loadReentryLock() != _TRUE, REENTRANT_CALL());
}
function _checkPaused() private view {
require(paused(), INVALID_PAUSE_STATUS());
}
function _checkNotPaused() private view {
require(!paused(), INVALID_PAUSE_STATUS());
}
function _checkNonZeroAddr(address _addr) private pure {
require(_addr != address(0), ZERO_ADDRESS());
}
function _checkNonZeroValue(uint256 _value) private pure {
require(_value != 0, ZERO_VALUE());
}
function _checkNonZeroBytes32(bytes32 _value) private pure {
require(_value != 0, ZERO_VALUE());
}
function _checkFromEither(address _addr1, address _addr2) private view {
require(msg.sender == _addr1 || msg.sender == _addr2, ACCESS_DENIED());
}
function _checkFrom(address _addr) private view {
require(msg.sender == _addr, ACCESS_DENIED());
}
function _checkFromOptional(address _addr) private view {
require(_addr == address(0) || msg.sender == _addr, ACCESS_DENIED());
}
}
contracts/shared/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);
}
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);
}
contracts/shared/signal/ISignalService.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "./ICheckpointStore.sol";
/// @title ISignalService
/// @notice The SignalService contract serves as a secure cross-chain message
/// passing system. It defines methods for sending and verifying signals with
/// merkle proofs. The trust assumption is that the target chain has secure
/// access to the merkle root (such as Taiko injects it in the anchor
/// transaction). With this, verifying a signal is reduced to simply verifying
/// a merkle proof.
/// @custom:security-contact security@taiko.xyz
interface ISignalService is ICheckpointStore {
/// @dev DEPRECATED
/// @dev Caching is no longer supported
enum CacheOption {
CACHE_NOTHING,
CACHE_SIGNAL_ROOT,
CACHE_STATE_ROOT,
CACHE_BOTH
}
struct HopProof {
/// @notice This hop's destination chain ID. If there is a next hop, this ID is the next
/// hop's source chain ID.
uint64 chainId;
/// @notice The ID of a source chain block whose state root has been synced to the hop's
/// destination chain.
/// Note that this block ID must be greater than or equal to the block ID where the signal
/// was sent on the source chain.
uint64 blockId;
/// @notice The state root or signal root of the source chain at the above blockId. This
/// value has been synced to the destination chain.
/// @dev To get both the blockId and the rootHash, apps should subscribe to the
/// ChainDataSynced event or query `topBlockId` first using the source chain's ID and
/// LibStrings.H_STATE_ROOT to get the most recent block ID synced, then call
/// `getSyncedChainData` to read the synchronized data.
bytes32 rootHash;
/// @notice Options to cache either the state roots or signal roots of middle-hops to the
/// current chain.
/// @dev DEPRECATED - this value will be ignored
CacheOption cacheOption;
/// @notice The signal service's account proof. If this value is empty, then `rootHash` will
/// be used as the signal root, otherwise, `rootHash` will be used as the state root.
bytes[] accountProof;
/// @notice The signal service's storage proof.
bytes[] storageProof;
}
/// @notice Emitted when a signal is sent.
/// @param app The address that initiated the signal.
/// @param signal The signal (message) that was sent.
/// @param slot The location in storage where this signal is stored.
/// @param value The value of the signal.
event SignalSent(address app, bytes32 signal, bytes32 slot, bytes32 value);
/// @notice Send a signal (message) by setting the storage slot to the same value as the signal
/// itself.
/// @param _signal The signal (message) to send.
/// @return slot_ The location in storage where this signal is stored.
function sendSignal(bytes32 _signal) external returns (bytes32 slot_);
/// @notice Checks whether a signal has been received on the target chain and caches the result if successful.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain. If this proof is empty, then we check if this signal has been marked as
/// received by TaikoL2.
/// @return numCacheOps_ The number of newly cached items.
function proveSignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
returns (uint256 numCacheOps_);
/// @notice Verifies if a signal has been received on the target chain.
/// This is the "readonly" version of proveSignalReceived.
/// @param _chainId The identifier for the source chain from which the
/// signal originated.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) to send.
/// @param _proof Merkle proof that the signal was persisted on the
/// source chain. If this proof is empty, then we check if this signal has been marked as
/// received by TaikoL2.
function verifySignalReceived(
uint64 _chainId,
address _app,
bytes32 _signal,
bytes calldata _proof
)
external
view;
/// @notice Verifies if a particular signal has already been sent.
/// @param _app The address that initiated the signal.
/// @param _signal The signal (message) that was sent.
/// @return true if the signal has been sent, otherwise false.
function isSignalSent(address _app, bytes32 _signal) external view returns (bool);
/// @notice Verifies if a particular signal has already been sent.
/// @param _signalSlot The location in storage where this signal is stored.
function isSignalSent(bytes32 _signalSlot) external view returns (bool);
}
node_modules/@openzeppelin/contracts-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;
}
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;
}
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;
}
}
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-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/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/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);
}
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);
}
}
}
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/proxy/utils/UUPSUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822.sol";
import "../ERC1967/ERC1967Upgrade.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
}
node_modules/@openzeppelin/contracts/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);
}
}
}
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
}
}
}
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/","solady/auth/=node_modules/solady/src/auth/","@optimism/=node_modules/optimism/","@sp1-contracts/=node_modules/sp1-contracts/contracts/src/","forge-std/=node_modules/forge-std/","@p256-verifier/contracts/=node_modules/p256-verifier/src/","@eth-fabric/urc/=node_modules/urc/src/","@automata-network/on-chain-pccs/=node_modules/@automata-network/on-chain-pccs/src/","@automata-network/automata-dcap-attestation/=node_modules/@automata-network/automata-dcap-attestation/","risc0/=node_modules/risc0-ethereum/contracts/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":"tuple","name":"_config","internalType":"struct IEtnaInbox.Config","components":[{"type":"address","name":"proofVerifier","internalType":"address"},{"type":"address","name":"signalService","internalType":"address"},{"type":"address","name":"stakingRegistry","internalType":"address"},{"type":"uint64","name":"l2ChainId","internalType":"uint64"},{"type":"uint64","name":"maxBatchBlocks","internalType":"uint64"}]}]},{"type":"error","name":"ACCESS_DENIED","inputs":[]},{"type":"error","name":"AnchorUnavailable","inputs":[]},{"type":"error","name":"BatchTooLarge","inputs":[]},{"type":"error","name":"BlobsRequired","inputs":[]},{"type":"error","name":"EtnaNotActive","inputs":[]},{"type":"error","name":"FUNC_NOT_IMPLEMENTED","inputs":[]},{"type":"error","name":"HeightOverflow","inputs":[]},{"type":"error","name":"INVALID_PAUSE_STATUS","inputs":[]},{"type":"error","name":"InvalidEpochLength","inputs":[]},{"type":"error","name":"InvalidGenesis","inputs":[]},{"type":"error","name":"InvalidGenesisCutoff","inputs":[]},{"type":"error","name":"NoProgress","inputs":[]},{"type":"error","name":"REENTRANT_CALL","inputs":[]},{"type":"error","name":"ZERO_ADDRESS","inputs":[]},{"type":"error","name":"ZERO_VALUE","inputs":[]},{"type":"error","name":"ZeroCommitteeConfigHash","inputs":[]},{"type":"error","name":"ZeroCommitteeRecord","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":"BatchLanded","inputs":[{"type":"uint64","name":"firstHeight","internalType":"uint64","indexed":false},{"type":"uint64","name":"lastHeight","internalType":"uint64","indexed":false},{"type":"bytes32","name":"lastBlockHash","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"lastStateRoot","internalType":"bytes32","indexed":false},{"type":"uint64","name":"l1ReferenceBlockNumber","internalType":"uint64","indexed":false},{"type":"bytes32","name":"statementHash","internalType":"bytes32","indexed":false},{"type":"address","name":"lander","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"EtnaInitialized","inputs":[{"type":"bytes32","name":"genesisBlockHash","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"genesisStateRoot","internalType":"bytes32","indexed":false},{"type":"uint64","name":"l1Block","internalType":"uint64","indexed":false},{"type":"uint64","name":"epochLenL2","internalType":"uint64","indexed":false},{"type":"uint64","name":"epochLenL1","internalType":"uint64","indexed":false},{"type":"uint64","name":"genesisCutoff","internalType":"uint64","indexed":false},{"type":"bytes32","name":"committeeRecordHash","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct IEtnaInbox.Activation","components":[{"type":"uint64","name":"genesisHeight","internalType":"uint64"},{"type":"uint64","name":"l1Block","internalType":"uint64"},{"type":"uint64","name":"epochLenL2","internalType":"uint64"},{"type":"uint64","name":"epochLenL1","internalType":"uint64"},{"type":"bytes32","name":"genesisBlockHash","internalType":"bytes32"},{"type":"bytes32","name":"genesisStateRoot","internalType":"bytes32"}]}],"name":"activation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"configHash_","internalType":"bytes32"}],"name":"committeeConfigHash","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"recordHash_","internalType":"bytes32"}],"name":"genesisCommitteeRecordHash","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"genesisCutoff","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"statementHash_","internalType":"bytes32"}],"name":"hashLandStatement","inputs":[{"type":"uint64","name":"_generation","internalType":"uint64"},{"type":"uint64","name":"_parentHeight","internalType":"uint64"},{"type":"bytes32","name":"_parentHash","internalType":"bytes32"},{"type":"tuple","name":"_input","internalType":"struct IEtnaInbox.LandInput","components":[{"type":"uint64","name":"lastHeight","internalType":"uint64"},{"type":"bytes32","name":"lastBlockHash","internalType":"bytes32"},{"type":"bytes32","name":"lastStateRoot","internalType":"bytes32"},{"type":"uint64","name":"l1ReferenceBlockNumber","internalType":"uint64"}]},{"type":"bytes32","name":"_l1ReferenceBlockHash","internalType":"bytes32"},{"type":"bytes32[]","name":"_blobHashes","internalType":"bytes32[]"}]},{"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":"tuple","name":"_params","internalType":"struct IEtnaInbox.GenesisParams","components":[{"type":"bytes32","name":"genesisBlockHash","internalType":"bytes32"},{"type":"bytes32","name":"genesisStateRoot","internalType":"bytes32"},{"type":"uint64","name":"epochLenL2","internalType":"uint64"},{"type":"uint64","name":"epochLenL1","internalType":"uint64"},{"type":"uint64","name":"genesisCutoff","internalType":"uint64"},{"type":"bytes32","name":"committeeRecordHash","internalType":"bytes32"},{"type":"bytes32","name":"committeeConfigHash","internalType":"bytes32"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"land","inputs":[{"type":"tuple","name":"_input","internalType":"struct IEtnaInbox.LandInput","components":[{"type":"uint64","name":"lastHeight","internalType":"uint64"},{"type":"bytes32","name":"lastBlockHash","internalType":"bytes32"},{"type":"bytes32","name":"lastStateRoot","internalType":"bytes32"},{"type":"uint64","name":"l1ReferenceBlockNumber","internalType":"uint64"}]},{"type":"bytes","name":"_proof","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct IEtnaInbox.LandedCheckpoint","components":[{"type":"uint64","name":"height","internalType":"uint64"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"}]}],"name":"lastCheckpoint","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"migrationState","inputs":[]},{"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":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"proxiableUUID","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"recoveryGeneration","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"resolver","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]}]
Contract Creation Code
0x61016060405230608052348015610014575f5ffd5b5060405161278838038061278883398101604081905261003391610248565b61003b61015b565b80516001600160a01b03166100635760405163538ba4f960e01b815260040160405180910390fd5b60208101516001600160a01b031661008e5760405163538ba4f960e01b815260040160405180910390fd5b60408101516001600160a01b03166100b95760405163538ba4f960e01b815260040160405180910390fd5b80606001516001600160401b03165f036100e65760405163ec73295960e01b815260040160405180910390fd5b80608001516001600160401b03165f036101135760405163ec73295960e01b815260040160405180910390fd5b80516001600160a01b0390811660c0526020820151811660e0526040820151166101005260608101516001600160401b039081166101205260809091015116610140526102e1565b5f54610100900460ff16156101c65760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614610215575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b038116811461022d575f5ffd5b919050565b80516001600160401b038116811461022d575f5ffd5b5f60a0828403128015610259575f5ffd5b5060405160a081016001600160401b038111828210171561028857634e487b7160e01b5f52604160045260245ffd5b60405261029483610217565b81526102a260208401610217565b60208201526102b360408401610217565b60408201526102c460608401610232565b60608201526102d560808401610232565b60808201529392505050565b60805160a05160c05160e0516101005161012051610140516124256103635f395f610eb701525f61141b01525f818161144b0152818161156b015261161901525f8181610bd6015261100801525f61110801525f61015901525f818161056e015281816105b701528181610699015281816106d901526107a101526124255ff3fe608060405260043610610147575f3560e01c80636b495f55116100b357806395806bd81161006d57806395806bd814610482578063cf4a9bc3146104a0578063d32e81a5146104b5578063dcf47eb014610509578063e30c397814610528578063f2fde38b14610545575f5ffd5b80636b495f55146103f6578063715018a61461041557806379ba5097146104295780638456cb591461043d5780638abf6077146104515780638da5cb5b14610465575f5ffd5b80633659cfe6116101045780633659cfe61461035b5780633f4ba83a1461037c5780634f1ef2861461039057806350a5f8fd146103a357806352d1902d146103c25780635c975abb146103d6575f5ffd5b806304f3bcec1461014b57806312a2f792146101965780631497a7de146101b857806320d0ac9f146101d75780633075db56146102095780633629c8de1461024e575b5f5ffd5b348015610156575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101a1575f5ffd5b506101025460405160ff909116815260200161018d565b3480156101c3575f5ffd5b50610116545b60405190815260200161018d565b3480156101e2575f5ffd5b50610117546001600160401b03165b6040516001600160401b03909116815260200161018d565b348015610214575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b604051901515815260200161018d565b348015610259575f5ffd5b506102ec6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c081018252610110546001600160401b038082168352600160401b820481166020840152600160801b8204811693830193909352600160c01b900490911660608201526101115460808201526101125460a082015290565b60405161018d91905f60c0820190506001600160401b0383511682526001600160401b0360208401511660208301526001600160401b0360408401511660408301526001600160401b0360608401511660608301526080830151608083015260a083015160a083015292915050565b348015610366575f5ffd5b5061037a610375366004611d12565b610564565b005b348015610387575f5ffd5b5061037a610634565b61037a61039e366004611d6f565b61068f565b3480156103ae575f5ffd5b506101c96103bd366004611e36565b610748565b3480156103cd575f5ffd5b506101c9610795565b3480156103e1575f5ffd5b5061023e60c954610100900460ff1660021490565b348015610401575f5ffd5b5061037a610410366004611ef0565b610846565b348015610420575f5ffd5b5061037a610d1c565b348015610434575f5ffd5b5061037a610d2d565b348015610448575f5ffd5b5061037a610da4565b34801561045c575f5ffd5b50610179610df9565b348015610470575f5ffd5b506033546001600160a01b0316610179565b34801561048d575f5ffd5b5061010c546001600160401b03166101f1565b3480156104ab575f5ffd5b5061010d546101c9565b3480156104c0575f5ffd5b506040805180820182525f8082526020918201528151808301835261010e546001600160401b031680825261010f5491830191825283519081529051918101919091520161018d565b348015610514575f5ffd5b5061037a610523366004611f2d565b610e07565b348015610533575f5ffd5b506065546001600160a01b0316610179565b348015610550575f5ffd5b5061037a61055f366004611d12565b61117c565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036105b55760405162461bcd60e51b81526004016105ac90611faa565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105e76111ed565b6001600160a01b03161461060d5760405162461bcd60e51b81526004016105ac90611ff6565b61061681611208565b604080515f8082526020820190925261063191839190611210565b50565b61063c61137a565b61065060c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a161068d335f6113ab565b565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036106d75760405162461bcd60e51b81526004016105ac90611faa565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107096111ed565b6001600160a01b03161461072f5760405162461bcd60e51b81526004016105ac90611ff6565b61073882611208565b61074482826001611210565b5050565b5f61078988888888888888808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506113b392505050565b98975050505050505050565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146108345760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105ac565b505f5160206123a95f395f51905f5290565b5f54610100900460ff161580801561086457505f54600160ff909116105b8061087d5750303b15801561087d57505f5460ff166001145b6108e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105ac565b5f805460ff191660011790558015610901575f805461ff0019166101001790555b8135158015906109145750602082013515155b6109315760405163156b26df60e31b815260040160405180910390fd5b60036109436060840160408501612042565b6001600160401b03161015801561097157506109656080830160608401612042565b6001600160401b031615155b61098e576040516388ac089760e01b815260040160405180910390fd5b6109a66109a160a0840160808501612042565b611551565b6109c357604051630377d3e160e61b815260040160405180910390fd5b60a08201355f036109e657604051627bdb0560e71b815260040160405180910390fd5b60c08201355f03610a0a5760405163390d011560e11b815260040160405180910390fd5b610a138361169c565b610102805460ff191660031790556040805160c0810182525f81526001600160401b034390811660208301529181810190610a549060608701908701612042565b6001600160401b03168152602001610a726080860160608701612042565b6001600160401b03908116825285356020808401919091528087013560409384015283516101108054928601519486015160608701519285166fffffffffffffffffffffffffffffffff1990941693909317600160401b95851695909502949094176fffffffffffffffffffffffffffffffff16600160801b928416929092026001600160c01b031691909117600160c01b91909216021790556080808201516101115560a09182015161011255610b2e918501908501612042565b61011780546001600160401b039290921667ffffffffffffffff1992831617905560a08401356101165560c084013561010d556040805180820182525f8082528635602092830181905261010e805490951690945561010f8490558251606081018452908152808201938452908601358183019081529151631934171960e31b8152905165ffffffffffff166004820152915160248301525160448201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c9a0b8c8906064015f604051808303815f87803b158015610c17575f5ffd5b505af1158015610c29573d5f5f3e3d5ffd5b507f2355a92149870da25c55d38f41906ea2e265232f265bd0e4892f5df31197303f92505084359050602085013583610c686060880160408901612042565b610c786080890160608a01612042565b610c8860a08a0160808b01612042565b6040805196875260208701959095526001600160401b03938416868601529183166060860152821660808501521660a08084019190915286013560c0830152519081900360e00190a1508015610d17575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b610d246116fa565b61068d5f611754565b60655433906001600160a01b03168114610d9b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105ac565b61063181611754565b610dac61176d565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a161068d3360016113ab565b5f610e026111ed565b905090565b610e0f61179f565b610e1960026117e4565b6101025460ff16600314610e40576040516383c575ff60e01b815260040160405180910390fd5b6040805180820190915261010e546001600160401b0316815261010f546020808301919091525f90610e7490860186612042565b9050815f01516001600160401b0316816001600160401b031611610eab57604051638b1075b960e01b815260040160405180910390fd5b81516001600160401b037f00000000000000000000000000000000000000000000000000000000000000001690610ee29083612078565b6001600160401b03161115610f0a576040516305beb17160e11b815260040160405180910390fd5b65ffffffffffff6001600160401b0382161115610f3a57604051633485a4d160e21b815260040160405180910390fd5b61010c54825160208401515f92610f7d926001600160401b039091169189610f70610f6b6080830160608401612042565b61180a565b610f7861197b565b6113b3565b6040805180820182526001600160401b03851680825260208a81013592810183905261010e805467ffffffffffffffff191690921790915561010f829055825160608101845265ffffffffffff80881682529181019283528a8401358185019081529351631934171960e31b81529051909116600482015290516024820152905160448201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c9a0b8c8906064015f604051808303815f87803b158015611051575f5ffd5b505af1158015611063573d5f5f3e3d5ffd5b505084513392507ff7748b2706521bf000553f53937ffbe593fa277d618ee71a4e2df74bed99eceb9150611098906001612097565b8460208a013560408b01356110b360808d0160608e01612042565b604080516001600160401b03968716815294861660208601528401929092526060830152909116608082015260a0810184905260c00160405180910390a26040516314bcf3dd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906314bcf3dd90611143905f9085908a908a906004016120b6565b5f6040518083038186803b158015611159575f5ffd5b505afa15801561116b573d5f5f3e3d5ffd5b50505050505050610d1760016117e4565b6111846116fa565b606580546001600160a01b0383166001600160a01b031990911681179091556111b56033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f5160206123a95f395f51905f52546001600160a01b031690565b6106316116fa565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561124357610d1783611a30565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561129d575060408051601f3d908101601f1916820190925261129a918101906120f2565b60015b6113005760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105ac565b5f5160206123a95f395f51905f52811461136e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105ac565b50610d17838383611acb565b61138e60c954610100900460ff1660021490565b61068d5760405163bae6e2a960e01b815260040160405180910390fd5b6107446116fa565b604080516101e0810182525f61012082018190526101408201819052610160820181905261018082018190526101a082018190526101c08201819052715441494b4f5f45544e415f4c414e445f563560701b8252466020808401919091526001600160401b037f00000000000000000000000000000000000000000000000000000000000000008116948401949094523060608401527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316608084015289841660a084015292881660c083015260e0820187905261010d54610100830152916114a690860186612042565b6001600160401b0316610120820152602085013561014082015260408501356101608201526114db6080860160608701612042565b6001600160401b03166101808201526101a08101849052604051611503908490602001612109565b60408051601f1981840301815291815281516020928301206101c08401525161152e9183910161213e565b604051602081830303815290604052805190602001209150509695505050505050565b5f43826001600160401b03161061156957505f919050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631f618cd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e991906120f2565b5f036115f657505f919050565b6040516001626ac92560e01b031981525f60048201526001600160401b038316907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ff9536db90602401606060405180830381865afa158015611666573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061168a9190612261565b516001600160401b0316111592915050565b5f54610100900460ff166116c25760405162461bcd60e51b81526004016105ac906122d3565b6116ca611af5565b6116e86001600160a01b038216156116e25781611754565b33611754565b5060c9805461ff001916610100179055565b6033546001600160a01b0316331461068d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b606580546001600160a01b031916905561063181611b1b565b61178160c954610100900460ff1660021490565b1561068d5760405163bae6e2a960e01b815260040160405180910390fd5b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff160361068d5760405163dfc60d8560e01b815260040160405180910390fd5b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b5f43826001600160401b031610611834576040516360776ed360e01b815260040160405180910390fd5b5f6118486001600160401b0384164361231e565b9050610100811161186557826001600160401b0316409150611954565b611fff811115611888576040516360776ed360e01b815260040160405180910390fd5b604080516001600160401b03851660208201525f91829171f90827f1c53a10cb7a02335b175320002935910160408051601f19818403018152908290526118ce91612331565b5f60405180830381855afa9150503d805f8114611906576040519150601f19603f3d011682016040523d82523d5f602084013e61190b565b606091505b509150915081801561191e575080516020145b61193b576040516360776ed360e01b815260040160405180910390fd5b8080602001905181019061194f91906120f2565b935050505b5f829003611975576040516360776ed360e01b815260040160405180910390fd5b50919050565b60605f5b8049156119965761198f81612347565b905061197f565b805f036119b65760405163595f3be960e11b815260040160405180910390fd5b806001600160401b038111156119ce576119ce611d2b565b6040519080825280602002602001820160405280156119f7578160200160208202803683370190505b5091505f5b81811015611a2b578049838281518110611a1857611a1861235f565b60209081029190910101526001016119fc565b505090565b6001600160a01b0381163b611a9d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105ac565b5f5160206123a95f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b611ad483611b6c565b5f82511180611ae05750805b15610d1757611aef8383611bab565b50505050565b5f54610100900460ff1661068d5760405162461bcd60e51b81526004016105ac906122d3565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b611b7581611a30565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060611bd083836040518060600160405280602781526020016123c960279139611bd9565b90505b92915050565b60605f5f856001600160a01b031685604051611bf59190612331565b5f60405180830381855af49150503d805f8114611c2d576040519150601f19603f3d011682016040523d82523d5f602084013e611c32565b606091505b5091509150611c4386838387611c4d565b9695505050505050565b60608315611cbb5782515f03611cb4576001600160a01b0385163b611cb45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105ac565b5081611cc5565b611cc58383611ccd565b949350505050565b815115611cdd5781518083602001fd5b8060405162461bcd60e51b81526004016105ac9190612373565b80356001600160a01b0381168114611d0d575f5ffd5b919050565b5f60208284031215611d22575f5ffd5b611bd082611cf7565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715611d6757611d67611d2b565b604052919050565b5f5f60408385031215611d80575f5ffd5b611d8983611cf7565b915060208301356001600160401b03811115611da3575f5ffd5b8301601f81018513611db3575f5ffd5b80356001600160401b03811115611dcc57611dcc611d2b565b611ddf601f8201601f1916602001611d3f565b818152866020838501011115611df3575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b6001600160401b0381168114610631575f5ffd5b5f60808284031215611975575f5ffd5b5f5f5f5f5f5f5f610120888a031215611e4d575f5ffd5b8735611e5881611e12565b96506020880135611e6881611e12565b955060408801359450611e7e8960608a01611e26565b935060e088013592506101008801356001600160401b03811115611ea0575f5ffd5b8801601f81018a13611eb0575f5ffd5b80356001600160401b03811115611ec5575f5ffd5b8a60208260051b8401011115611ed9575f5ffd5b602082019350809250505092959891949750929550565b5f5f828403610100811215611f03575f5ffd5b611f0c84611cf7565b925060e0601f1982011215611f1f575f5ffd5b506020830190509250929050565b5f5f5f60a08486031215611f3f575f5ffd5b611f498585611e26565b925060808401356001600160401b03811115611f63575f5ffd5b8401601f81018613611f73575f5ffd5b80356001600160401b03811115611f88575f5ffd5b866020828401011115611f99575f5ffd5b939660209190910195509293505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b5f60208284031215612052575f5ffd5b813561205d81611e12565b9392505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b038281168282160390811115611bd357611bd3612064565b6001600160401b038181168382160190811115611bd357611bd3612064565b84815283602082015260606040820152816060820152818360808301375f818301608090810191909152601f909201601f191601019392505050565b5f60208284031215612102575f5ffd5b5051919050565b81515f90829060208501835b82811015612133578151845260209384019390910190600101612115565b509195945050505050565b5f6101e0820190508251825260208301516020830152604083015161216e60408401826001600160401b03169052565b50606083015161218960608401826001600160a01b03169052565b5060808301516121a460808401826001600160a01b03169052565b5060a08301516121bf60a08401826001600160401b03169052565b5060c08301516121da60c08401826001600160401b03169052565b5060e083015160e083015261010083015161010083015261012083015161220d6101208401826001600160401b03169052565b506101408301516101408301526101608301516101608301526101808301516122426101808401826001600160401b03169052565b506101a08301516101a08301526101c08301516101c083015292915050565b5f6060828403128015612272575f5ffd5b50604051606081016001600160401b038111828210171561229557612295611d2b565b60405282516122a381611e12565b8152602083015163ffffffff811681146122bb575f5ffd5b60208201526040928301519281019290925250919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b81810381811115611bd357611bd3612064565b5f82518060208501845e5f920191825250919050565b5f6001820161235857612358612064565b5060010190565b634e487b7160e01b5f52603260045260245ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202399a769353d7bb4b4db6feb272cff380be1383a8fb873237ce53fbbac69c69364736f6c634300081e0033000000000000000000000000044c2e53e9edddd1353a9d923fa39c1fa821e88e0000000000000000000000009a3a019b2820ae3d396120fb9b2782d37be4799c000000000000000000000000b261c6facc0707b674c7491338412fdf44733a4b0000000000000000000000000000000000000000000000000000000000028c590000000000000000000000000000000000000000000000000000000000000080
Deployed ByteCode
0x608060405260043610610147575f3560e01c80636b495f55116100b357806395806bd81161006d57806395806bd814610482578063cf4a9bc3146104a0578063d32e81a5146104b5578063dcf47eb014610509578063e30c397814610528578063f2fde38b14610545575f5ffd5b80636b495f55146103f6578063715018a61461041557806379ba5097146104295780638456cb591461043d5780638abf6077146104515780638da5cb5b14610465575f5ffd5b80633659cfe6116101045780633659cfe61461035b5780633f4ba83a1461037c5780634f1ef2861461039057806350a5f8fd146103a357806352d1902d146103c25780635c975abb146103d6575f5ffd5b806304f3bcec1461014b57806312a2f792146101965780631497a7de146101b857806320d0ac9f146101d75780633075db56146102095780633629c8de1461024e575b5f5ffd5b348015610156575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101a1575f5ffd5b506101025460405160ff909116815260200161018d565b3480156101c3575f5ffd5b50610116545b60405190815260200161018d565b3480156101e2575f5ffd5b50610117546001600160401b03165b6040516001600160401b03909116815260200161018d565b348015610214575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b604051901515815260200161018d565b348015610259575f5ffd5b506102ec6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c081018252610110546001600160401b038082168352600160401b820481166020840152600160801b8204811693830193909352600160c01b900490911660608201526101115460808201526101125460a082015290565b60405161018d91905f60c0820190506001600160401b0383511682526001600160401b0360208401511660208301526001600160401b0360408401511660408301526001600160401b0360608401511660608301526080830151608083015260a083015160a083015292915050565b348015610366575f5ffd5b5061037a610375366004611d12565b610564565b005b348015610387575f5ffd5b5061037a610634565b61037a61039e366004611d6f565b61068f565b3480156103ae575f5ffd5b506101c96103bd366004611e36565b610748565b3480156103cd575f5ffd5b506101c9610795565b3480156103e1575f5ffd5b5061023e60c954610100900460ff1660021490565b348015610401575f5ffd5b5061037a610410366004611ef0565b610846565b348015610420575f5ffd5b5061037a610d1c565b348015610434575f5ffd5b5061037a610d2d565b348015610448575f5ffd5b5061037a610da4565b34801561045c575f5ffd5b50610179610df9565b348015610470575f5ffd5b506033546001600160a01b0316610179565b34801561048d575f5ffd5b5061010c546001600160401b03166101f1565b3480156104ab575f5ffd5b5061010d546101c9565b3480156104c0575f5ffd5b506040805180820182525f8082526020918201528151808301835261010e546001600160401b031680825261010f5491830191825283519081529051918101919091520161018d565b348015610514575f5ffd5b5061037a610523366004611f2d565b610e07565b348015610533575f5ffd5b506065546001600160a01b0316610179565b348015610550575f5ffd5b5061037a61055f366004611d12565b61117c565b6001600160a01b037f0000000000000000000000002fa4805846c3a81563e4b34c9f91115532aaeec41630036105b55760405162461bcd60e51b81526004016105ac90611faa565b60405180910390fd5b7f0000000000000000000000002fa4805846c3a81563e4b34c9f91115532aaeec46001600160a01b03166105e76111ed565b6001600160a01b03161461060d5760405162461bcd60e51b81526004016105ac90611ff6565b61061681611208565b604080515f8082526020820190925261063191839190611210565b50565b61063c61137a565b61065060c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a161068d335f6113ab565b565b6001600160a01b037f0000000000000000000000002fa4805846c3a81563e4b34c9f91115532aaeec41630036106d75760405162461bcd60e51b81526004016105ac90611faa565b7f0000000000000000000000002fa4805846c3a81563e4b34c9f91115532aaeec46001600160a01b03166107096111ed565b6001600160a01b03161461072f5760405162461bcd60e51b81526004016105ac90611ff6565b61073882611208565b61074482826001611210565b5050565b5f61078988888888888888808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152506113b392505050565b98975050505050505050565b5f306001600160a01b037f0000000000000000000000002fa4805846c3a81563e4b34c9f91115532aaeec416146108345760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016105ac565b505f5160206123a95f395f51905f5290565b5f54610100900460ff161580801561086457505f54600160ff909116105b8061087d5750303b15801561087d57505f5460ff166001145b6108e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016105ac565b5f805460ff191660011790558015610901575f805461ff0019166101001790555b8135158015906109145750602082013515155b6109315760405163156b26df60e31b815260040160405180910390fd5b60036109436060840160408501612042565b6001600160401b03161015801561097157506109656080830160608401612042565b6001600160401b031615155b61098e576040516388ac089760e01b815260040160405180910390fd5b6109a66109a160a0840160808501612042565b611551565b6109c357604051630377d3e160e61b815260040160405180910390fd5b60a08201355f036109e657604051627bdb0560e71b815260040160405180910390fd5b60c08201355f03610a0a5760405163390d011560e11b815260040160405180910390fd5b610a138361169c565b610102805460ff191660031790556040805160c0810182525f81526001600160401b034390811660208301529181810190610a549060608701908701612042565b6001600160401b03168152602001610a726080860160608701612042565b6001600160401b03908116825285356020808401919091528087013560409384015283516101108054928601519486015160608701519285166fffffffffffffffffffffffffffffffff1990941693909317600160401b95851695909502949094176fffffffffffffffffffffffffffffffff16600160801b928416929092026001600160c01b031691909117600160c01b91909216021790556080808201516101115560a09182015161011255610b2e918501908501612042565b61011780546001600160401b039290921667ffffffffffffffff1992831617905560a08401356101165560c084013561010d556040805180820182525f8082528635602092830181905261010e805490951690945561010f8490558251606081018452908152808201938452908601358183019081529151631934171960e31b8152905165ffffffffffff166004820152915160248301525160448201526001600160a01b037f0000000000000000000000009a3a019b2820ae3d396120fb9b2782d37be4799c169063c9a0b8c8906064015f604051808303815f87803b158015610c17575f5ffd5b505af1158015610c29573d5f5f3e3d5ffd5b507f2355a92149870da25c55d38f41906ea2e265232f265bd0e4892f5df31197303f92505084359050602085013583610c686060880160408901612042565b610c786080890160608a01612042565b610c8860a08a0160808b01612042565b6040805196875260208701959095526001600160401b03938416868601529183166060860152821660808501521660a08084019190915286013560c0830152519081900360e00190a1508015610d17575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b610d246116fa565b61068d5f611754565b60655433906001600160a01b03168114610d9b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105ac565b61063181611754565b610dac61176d565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a161068d3360016113ab565b5f610e026111ed565b905090565b610e0f61179f565b610e1960026117e4565b6101025460ff16600314610e40576040516383c575ff60e01b815260040160405180910390fd5b6040805180820190915261010e546001600160401b0316815261010f546020808301919091525f90610e7490860186612042565b9050815f01516001600160401b0316816001600160401b031611610eab57604051638b1075b960e01b815260040160405180910390fd5b81516001600160401b037f00000000000000000000000000000000000000000000000000000000000000801690610ee29083612078565b6001600160401b03161115610f0a576040516305beb17160e11b815260040160405180910390fd5b65ffffffffffff6001600160401b0382161115610f3a57604051633485a4d160e21b815260040160405180910390fd5b61010c54825160208401515f92610f7d926001600160401b039091169189610f70610f6b6080830160608401612042565b61180a565b610f7861197b565b6113b3565b6040805180820182526001600160401b03851680825260208a81013592810183905261010e805467ffffffffffffffff191690921790915561010f829055825160608101845265ffffffffffff80881682529181019283528a8401358185019081529351631934171960e31b81529051909116600482015290516024820152905160448201529091507f0000000000000000000000009a3a019b2820ae3d396120fb9b2782d37be4799c6001600160a01b03169063c9a0b8c8906064015f604051808303815f87803b158015611051575f5ffd5b505af1158015611063573d5f5f3e3d5ffd5b505084513392507ff7748b2706521bf000553f53937ffbe593fa277d618ee71a4e2df74bed99eceb9150611098906001612097565b8460208a013560408b01356110b360808d0160608e01612042565b604080516001600160401b03968716815294861660208601528401929092526060830152909116608082015260a0810184905260c00160405180910390a26040516314bcf3dd60e01b81526001600160a01b037f000000000000000000000000044c2e53e9edddd1353a9d923fa39c1fa821e88e16906314bcf3dd90611143905f9085908a908a906004016120b6565b5f6040518083038186803b158015611159575f5ffd5b505afa15801561116b573d5f5f3e3d5ffd5b50505050505050610d1760016117e4565b6111846116fa565b606580546001600160a01b0383166001600160a01b031990911681179091556111b56033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f5160206123a95f395f51905f52546001600160a01b031690565b6106316116fa565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561124357610d1783611a30565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa92505050801561129d575060408051601f3d908101601f1916820190925261129a918101906120f2565b60015b6113005760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016105ac565b5f5160206123a95f395f51905f52811461136e5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016105ac565b50610d17838383611acb565b61138e60c954610100900460ff1660021490565b61068d5760405163bae6e2a960e01b815260040160405180910390fd5b6107446116fa565b604080516101e0810182525f61012082018190526101408201819052610160820181905261018082018190526101a082018190526101c08201819052715441494b4f5f45544e415f4c414e445f563560701b8252466020808401919091526001600160401b037f0000000000000000000000000000000000000000000000000000000000028c598116948401949094523060608401527f000000000000000000000000b261c6facc0707b674c7491338412fdf44733a4b6001600160a01b0316608084015289841660a084015292881660c083015260e0820187905261010d54610100830152916114a690860186612042565b6001600160401b0316610120820152602085013561014082015260408501356101608201526114db6080860160608701612042565b6001600160401b03166101808201526101a08101849052604051611503908490602001612109565b60408051601f1981840301815291815281516020928301206101c08401525161152e9183910161213e565b604051602081830303815290604052805190602001209150509695505050505050565b5f43826001600160401b03161061156957505f919050565b7f000000000000000000000000b261c6facc0707b674c7491338412fdf44733a4b6001600160a01b0316631f618cd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e991906120f2565b5f036115f657505f919050565b6040516001626ac92560e01b031981525f60048201526001600160401b038316907f000000000000000000000000b261c6facc0707b674c7491338412fdf44733a4b6001600160a01b03169063ff9536db90602401606060405180830381865afa158015611666573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061168a9190612261565b516001600160401b0316111592915050565b5f54610100900460ff166116c25760405162461bcd60e51b81526004016105ac906122d3565b6116ca611af5565b6116e86001600160a01b038216156116e25781611754565b33611754565b5060c9805461ff001916610100179055565b6033546001600160a01b0316331461068d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105ac565b606580546001600160a01b031916905561063181611b1b565b61178160c954610100900460ff1660021490565b1561068d5760405163bae6e2a960e01b815260040160405180910390fd5b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff160361068d5760405163dfc60d8560e01b815260040160405180910390fd5b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b5f43826001600160401b031610611834576040516360776ed360e01b815260040160405180910390fd5b5f6118486001600160401b0384164361231e565b9050610100811161186557826001600160401b0316409150611954565b611fff811115611888576040516360776ed360e01b815260040160405180910390fd5b604080516001600160401b03851660208201525f91829171f90827f1c53a10cb7a02335b175320002935910160408051601f19818403018152908290526118ce91612331565b5f60405180830381855afa9150503d805f8114611906576040519150601f19603f3d011682016040523d82523d5f602084013e61190b565b606091505b509150915081801561191e575080516020145b61193b576040516360776ed360e01b815260040160405180910390fd5b8080602001905181019061194f91906120f2565b935050505b5f829003611975576040516360776ed360e01b815260040160405180910390fd5b50919050565b60605f5b8049156119965761198f81612347565b905061197f565b805f036119b65760405163595f3be960e11b815260040160405180910390fd5b806001600160401b038111156119ce576119ce611d2b565b6040519080825280602002602001820160405280156119f7578160200160208202803683370190505b5091505f5b81811015611a2b578049838281518110611a1857611a1861235f565b60209081029190910101526001016119fc565b505090565b6001600160a01b0381163b611a9d5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016105ac565b5f5160206123a95f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b611ad483611b6c565b5f82511180611ae05750805b15610d1757611aef8383611bab565b50505050565b5f54610100900460ff1661068d5760405162461bcd60e51b81526004016105ac906122d3565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b611b7581611a30565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060611bd083836040518060600160405280602781526020016123c960279139611bd9565b90505b92915050565b60605f5f856001600160a01b031685604051611bf59190612331565b5f60405180830381855af49150503d805f8114611c2d576040519150601f19603f3d011682016040523d82523d5f602084013e611c32565b606091505b5091509150611c4386838387611c4d565b9695505050505050565b60608315611cbb5782515f03611cb4576001600160a01b0385163b611cb45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016105ac565b5081611cc5565b611cc58383611ccd565b949350505050565b815115611cdd5781518083602001fd5b8060405162461bcd60e51b81526004016105ac9190612373565b80356001600160a01b0381168114611d0d575f5ffd5b919050565b5f60208284031215611d22575f5ffd5b611bd082611cf7565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715611d6757611d67611d2b565b604052919050565b5f5f60408385031215611d80575f5ffd5b611d8983611cf7565b915060208301356001600160401b03811115611da3575f5ffd5b8301601f81018513611db3575f5ffd5b80356001600160401b03811115611dcc57611dcc611d2b565b611ddf601f8201601f1916602001611d3f565b818152866020838501011115611df3575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b6001600160401b0381168114610631575f5ffd5b5f60808284031215611975575f5ffd5b5f5f5f5f5f5f5f610120888a031215611e4d575f5ffd5b8735611e5881611e12565b96506020880135611e6881611e12565b955060408801359450611e7e8960608a01611e26565b935060e088013592506101008801356001600160401b03811115611ea0575f5ffd5b8801601f81018a13611eb0575f5ffd5b80356001600160401b03811115611ec5575f5ffd5b8a60208260051b8401011115611ed9575f5ffd5b602082019350809250505092959891949750929550565b5f5f828403610100811215611f03575f5ffd5b611f0c84611cf7565b925060e0601f1982011215611f1f575f5ffd5b506020830190509250929050565b5f5f5f60a08486031215611f3f575f5ffd5b611f498585611e26565b925060808401356001600160401b03811115611f63575f5ffd5b8401601f81018613611f73575f5ffd5b80356001600160401b03811115611f88575f5ffd5b866020828401011115611f99575f5ffd5b939660209190910195509293505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b5f60208284031215612052575f5ffd5b813561205d81611e12565b9392505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b038281168282160390811115611bd357611bd3612064565b6001600160401b038181168382160190811115611bd357611bd3612064565b84815283602082015260606040820152816060820152818360808301375f818301608090810191909152601f909201601f191601019392505050565b5f60208284031215612102575f5ffd5b5051919050565b81515f90829060208501835b82811015612133578151845260209384019390910190600101612115565b509195945050505050565b5f6101e0820190508251825260208301516020830152604083015161216e60408401826001600160401b03169052565b50606083015161218960608401826001600160a01b03169052565b5060808301516121a460808401826001600160a01b03169052565b5060a08301516121bf60a08401826001600160401b03169052565b5060c08301516121da60c08401826001600160401b03169052565b5060e083015160e083015261010083015161010083015261012083015161220d6101208401826001600160401b03169052565b506101408301516101408301526101608301516101608301526101808301516122426101808401826001600160401b03169052565b506101a08301516101a08301526101c08301516101c083015292915050565b5f6060828403128015612272575f5ffd5b50604051606081016001600160401b038111828210171561229557612295611d2b565b60405282516122a381611e12565b8152602083015163ffffffff811681146122bb575f5ffd5b60208201526040928301519281019290925250919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b81810381811115611bd357611bd3612064565b5f82518060208501845e5f920191825250919050565b5f6001820161235857612358612064565b5060010190565b634e487b7160e01b5f52603260045260245ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202399a769353d7bb4b4db6feb272cff380be1383a8fb873237ce53fbbac69c69364736f6c634300081e0033