Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- EtnaStakingRegistry
- Optimization enabled
- true
- Compiler version
- v0.8.30+commit.73712a01
- Optimization runs
- 200
- EVM Version
- prague
- Verified at
- 2026-10-12T09:04:25.065387Z
Constructor Arguments
0x000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af00000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000007fffffffffffffff
Arg [0] (address) : 0xf4d761f2e88e7d572aa74feb135b7cdafd727af0
Arg [1] (uint256) : 1000000000000000000
Arg [2] (uint64) : 0
Arg [3] (uint64) : 64
Arg [4] (uint64) : 64
Arg [5] (uint64) : 9223372036854775807
contracts/layer1/etna/impl/EtnaStakingRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { IEtnaStakingRegistry } from "../iface/IEtnaStakingRegistry.sol";
import { LibEntriesTree } from "../libs/LibEntriesTree.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { EssentialContract } from "src/shared/common/EssentialContract.sol";
import "./EtnaStakingRegistry_Layout.sol"; // DO NOT DELETE
/// @title EtnaStakingRegistry
/// @notice The TAIKO staking registry of the Etna PoS chain: append-only validator entries, one
/// checkpoint per L1 block that changes an entry, and an incremental entries Merkle root.
/// @dev All state lives in the ERC-7201 namespace `taiko.etna.registry` (`RegistryStorage`),
/// whose slots the Etna node proves; see `IEtnaStakingRegistry`. The contract upholds the node's
/// registry obligations: checkpoints have strictly increasing `l1Block`s, every L1 block that
/// changes an entry has one, each covers every entry as it stands at the end of its block, and
/// no two entries whose exits are not yet effective share a pubkey.
/// @custom:security-contact security@taiko.xyz
contract EtnaStakingRegistry is EssentialContract, IEtnaStakingRegistry {
using SafeERC20 for IERC20;
// ---------------------------------------------------------------
// Structs
// ---------------------------------------------------------------
/// @custom:storage-location erc7201:taiko.etna.registry
struct RegistryStorage {
/// @dev Slot `R`: one checkpoint per L1 block that changed an entry.
Checkpoint[] checkpoints;
/// @dev Slot `R + 1`: the entries, indexed by bond id.
Entry[] entries;
/// @dev Slot `R + 2`.
mapping(uint256 bondId => address owner) bondOwner;
/// @dev Slot `R + 3`.
mapping(uint256 bondId => bool withdrawn) withdrawn;
/// @dev Slot `R + 4`: the bond id plus one of the latest entry registered with a pubkey.
mapping(bytes32 pubkey => uint256 bondIdPlusOne) keyHolder;
/// @dev Slot `R + 5`: the `LibEntriesTree` nodes.
mapping(uint256 node => bytes32 hash) tree;
}
// ---------------------------------------------------------------
// Constants
// ---------------------------------------------------------------
/// @notice The maximum number of entries, exited ones included (the tree capacity).
uint256 public constant MAX_ENTRIES = LibEntriesTree.CAPACITY;
/// @dev The ERC-7201 base slot `R` of `RegistryStorage`:
/// `keccak256(abi.encode(uint256(keccak256("taiko.etna.registry")) - 1)) & ~bytes32(uint256(0xff))`.
bytes32 private constant _REGISTRY_STORAGE_SLOT =
0x46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b8000;
/// @dev The `exitEffectiveL1` of an entry whose exit was not requested.
uint64 private constant _NO_EXIT = type(uint64).max;
// ---------------------------------------------------------------
// Immutable Variables
// ---------------------------------------------------------------
/// @notice The TAIKO token staked in this registry.
IERC20 public immutable taikoToken;
/// @notice The minimum stake of a registration, in TAIKO base units.
uint256 public immutable minStake;
/// @notice The number of L1 blocks from registration until the entry is active.
uint64 public immutable activationDelay;
/// @notice The number of L1 blocks from the exit request (or the activation, if later) until
/// the exit takes effect.
uint64 public immutable exitDelay;
/// @notice The number of L1 blocks from the effective exit until the stake can be withdrawn.
uint64 public immutable withdrawalDelay;
/// @notice The heartbeat window `W` in L1 blocks; equals the node's `heartbeat_window`.
uint64 public immutable heartbeatWindow;
// ---------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------
/// @notice Sets the registry's immutable parameters.
/// @param _taikoToken The TAIKO token.
/// @param _minStake The minimum stake of a registration; must be non-zero.
/// @param _activationDelay The activation delay in L1 blocks.
/// @param _exitDelay The exit delay in L1 blocks.
/// @param _withdrawalDelay The withdrawal delay in L1 blocks.
/// @param _heartbeatWindow The heartbeat window in L1 blocks; must be non-zero.
constructor(
address _taikoToken,
uint256 _minStake,
uint64 _activationDelay,
uint64 _exitDelay,
uint64 _withdrawalDelay,
uint64 _heartbeatWindow
) {
require(_taikoToken != address(0), ZERO_ADDRESS());
require(_minStake != 0, ZERO_VALUE());
require(_heartbeatWindow != 0, InvalidHeartbeatWindow());
taikoToken = IERC20(_taikoToken);
minStake = _minStake;
activationDelay = _activationDelay;
exitDelay = _exitDelay;
withdrawalDelay = _withdrawalDelay;
heartbeatWindow = _heartbeatWindow;
}
// ---------------------------------------------------------------
// External & Public Functions
// ---------------------------------------------------------------
/// @notice Initializes the owner of the registry.
/// @param _owner The owner of this contract; `msg.sender` if zero.
function init(address _owner) external initializer {
__Essential_init(_owner);
}
/// @inheritdoc IEtnaStakingRegistry
function register(
bytes32 _pubkey,
uint256 _amount
)
external
nonReentrant
returns (uint256 bondId_)
{
require(_amount >= minStake, StakeTooLow());
require(_pubkey != 0, ZeroPubkey());
RegistryStorage storage $ = _registryStorage();
bondId_ = $.entries.length;
require(bondId_ < MAX_ENTRIES, RegistryFull());
uint256 holder = $.keyHolder[_pubkey];
if (holder != 0) {
require($.entries[holder - 1].exitEffectiveL1 <= block.number, PubkeyInUse());
}
Entry memory entry = Entry({
pubkey: _pubkey,
effStake: _amount,
activeFromL1: uint64(block.number) + activationDelay,
exitEffectiveL1: _NO_EXIT,
lastHeartbeatAt: 0,
lastHeartbeatSeq: 0
});
$.entries.push(entry);
$.bondOwner[bondId_] = msg.sender;
$.keyHolder[_pubkey] = bondId_ + 1;
_commit($, bondId_ + 1, bondId_, entry);
taikoToken.safeTransferFrom(msg.sender, address(this), _amount);
emit Registered(bondId_, msg.sender, _pubkey, _amount, entry.activeFromL1);
}
/// @inheritdoc IEtnaStakingRegistry
function heartbeat(uint256 _bondId) external nonReentrant {
RegistryStorage storage $ = _registryStorage();
uint256 count = _checkBondOwner($, _bondId);
Entry memory entry = $.entries[_bondId];
require(block.number < entry.exitEffectiveL1, AlreadyExited());
uint64 windowStart = uint64(block.number / heartbeatWindow * heartbeatWindow);
require(
entry.lastHeartbeatSeq == 0 || windowStart > entry.lastHeartbeatAt,
HeartbeatAlreadyRecorded()
);
entry.lastHeartbeatAt = windowStart;
++entry.lastHeartbeatSeq;
Entry storage stored = $.entries[_bondId];
stored.lastHeartbeatAt = windowStart;
stored.lastHeartbeatSeq = entry.lastHeartbeatSeq;
_commit($, count, _bondId, entry);
emit HeartbeatRecorded(_bondId, windowStart, entry.lastHeartbeatSeq);
}
/// @inheritdoc IEtnaStakingRegistry
function requestExit(uint256 _bondId) external nonReentrant {
RegistryStorage storage $ = _registryStorage();
uint256 count = _checkBondOwner($, _bondId);
Entry memory entry = $.entries[_bondId];
require(entry.exitEffectiveL1 == _NO_EXIT, ExitAlreadyRequested());
uint64 exitFrom =
block.number > entry.activeFromL1 ? uint64(block.number) : entry.activeFromL1;
entry.exitEffectiveL1 = exitFrom + exitDelay;
$.entries[_bondId].exitEffectiveL1 = entry.exitEffectiveL1;
_commit($, count, _bondId, entry);
emit ExitRequested(_bondId, entry.exitEffectiveL1);
}
/// @inheritdoc IEtnaStakingRegistry
function withdraw(uint256 _bondId, address _to) external nonReentrant nonZeroAddr(_to) {
RegistryStorage storage $ = _registryStorage();
_checkBondOwner($, _bondId);
require(!$.withdrawn[_bondId], AlreadyWithdrawn());
Entry storage entry = $.entries[_bondId];
uint64 exitEffectiveL1 = entry.exitEffectiveL1;
require(exitEffectiveL1 != _NO_EXIT, ExitNotRequested());
require(block.number >= uint256(exitEffectiveL1) + withdrawalDelay, WithdrawalNotReady());
$.withdrawn[_bondId] = true;
uint256 amount = entry.effStake;
taikoToken.safeTransfer(_to, amount);
emit StakeWithdrawn(_bondId, _to, amount);
}
/// @inheritdoc IEtnaStakingRegistry
function checkpointCount() external view returns (uint256) {
return _registryStorage().checkpoints.length;
}
/// @inheritdoc IEtnaStakingRegistry
function checkpointAt(uint256 _index) external view returns (Checkpoint memory) {
RegistryStorage storage $ = _registryStorage();
require(_index < $.checkpoints.length, UnknownCheckpoint());
return $.checkpoints[_index];
}
/// @inheritdoc IEtnaStakingRegistry
function entryCount() external view returns (uint256) {
return _registryStorage().entries.length;
}
/// @inheritdoc IEtnaStakingRegistry
function entryAt(uint256 _bondId) external view returns (Entry memory) {
RegistryStorage storage $ = _registryStorage();
require(_bondId < $.entries.length, UnknownBond());
return $.entries[_bondId];
}
/// @inheritdoc IEtnaStakingRegistry
function entriesRoot() external view returns (bytes32) {
RegistryStorage storage $ = _registryStorage();
return LibEntriesTree.root($.tree, $.entries.length);
}
/// @inheritdoc IEtnaStakingRegistry
function bondOwnerOf(uint256 _bondId) external view returns (address) {
return _registryStorage().bondOwner[_bondId];
}
/// @inheritdoc IEtnaStakingRegistry
function isWithdrawn(uint256 _bondId) external view returns (bool) {
return _registryStorage().withdrawn[_bondId];
}
// ---------------------------------------------------------------
// Private Functions
// ---------------------------------------------------------------
/// @dev Checks that `_bondId` exists and that the caller owns it.
/// @param $ The registry storage.
/// @param _bondId The bond id.
/// @return count_ The number of entries.
function _checkBondOwner(
RegistryStorage storage $,
uint256 _bondId
)
private
view
returns (uint256 count_)
{
count_ = $.entries.length;
require(_bondId < count_, UnknownBond());
require($.bondOwner[_bondId] == msg.sender, NotBondOwner());
}
/// @dev Rewrites the leaf of entry `_bondId` and records the new root in the current block's
/// checkpoint: overwritten if the latest checkpoint is this block's, appended otherwise.
/// @param $ The registry storage.
/// @param _count The number of entries.
/// @param _bondId The changed entry's bond id.
/// @param _entry The changed entry's new value.
function _commit(
RegistryStorage storage $,
uint256 _count,
uint256 _bondId,
Entry memory _entry
)
private
{
bytes32 root =
LibEntriesTree.update($.tree, _count, _bondId, LibEntriesTree.leaf(_bondId, _entry));
uint64 l1Block = uint64(block.number);
// `_count` is at most MAX_ENTRIES, so it fits in a uint32.
uint32 count = uint32(_count);
uint256 index = $.checkpoints.length;
if (index != 0 && $.checkpoints[index - 1].l1Block == l1Block) {
--index;
Checkpoint storage last = $.checkpoints[index];
last.count = count;
last.entriesRoot = root;
} else {
$.checkpoints.push(Checkpoint({ l1Block: l1Block, count: count, entriesRoot: root }));
}
emit CheckpointWritten(index, l1Block, count, root);
}
/// @dev Returns the registry's ERC-7201 storage.
/// @return $ The registry storage.
function _registryStorage() private pure returns (RegistryStorage storage $) {
assembly {
$.slot := _REGISTRY_STORAGE_SLOT
}
}
// ---------------------------------------------------------------
// Custom Errors
// ---------------------------------------------------------------
error AlreadyExited();
error AlreadyWithdrawn();
error ExitAlreadyRequested();
error ExitNotRequested();
error HeartbeatAlreadyRecorded();
error InvalidHeartbeatWindow();
error NotBondOwner();
error PubkeyInUse();
error RegistryFull();
error StakeTooLow();
error UnknownBond();
error UnknownCheckpoint();
error WithdrawalNotReady();
error ZeroPubkey();
}
node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
node_modules/@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
contracts/layer1/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/EtnaStakingRegistry_Layout.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/// @title EtnaStakingRegistryLayout
/// @notice Storage layout documentation for EtnaStakingRegistry
/// @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
contracts/layer1/etna/libs/LibEntriesTree.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import { IEtnaStakingRegistry } from "../iface/IEtnaStakingRegistry.sol";
/// @title LibEntriesTree
/// @notice Incremental Merkle tree over the staking registry's entries, and the entry leaf.
/// @dev The tree has a fixed depth of 12 (4096 leaf positions). Leaf `i` is the hash of entry
/// `i`; inner nodes are `keccak256(left ‖ right)`. A node that was never written reads as the
/// zero hash of its level: `zero(0) = 0` and `zero(l) = keccak256(zero(l - 1) ‖ zero(l - 1))`.
///
/// The root over the first `count` leaves is the node at level `ceil(log2(count))`, index 0,
/// which equals the root of those leaves padded with zero leaves to the next power of two. This
/// is the Etna node's `entries_root` (`crates/abci/src/committee` of taiko-client-rs).
///
/// Node `(level, index)` lives at key `(level << 32) | index` of the caller's mapping.
///
/// Leaves are appended in index order and may be rewritten afterwards. Because the leaf count
/// never decreases, `update` stops at the root level of the current count: a node above it covers
/// no leaf outside its leftmost child, is never read before the count grows past it, and is
/// written on the path of the leaf whose append makes it the root.
/// @custom:security-contact security@taiko.xyz
library LibEntriesTree {
// ---------------------------------------------------------------
// Constants
// ---------------------------------------------------------------
/// @dev The tree depth.
uint256 internal constant DEPTH = 12;
/// @dev The number of leaf positions, `2 ** DEPTH`.
uint256 internal constant CAPACITY = 4096;
/// @dev The domain tag of entry leaves: "ETNA_REG_ENTRY", right-padded with zero bytes.
bytes32 internal constant ENTRY_TAG = bytes32("ETNA_REG_ENTRY");
/// @dev `zero(l)` for `l = 1..12`; `zero(0)` is `bytes32(0)`.
bytes32 private constant _Z1 =
0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5;
bytes32 private constant _Z2 =
0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30;
bytes32 private constant _Z3 =
0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85;
bytes32 private constant _Z4 =
0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344;
bytes32 private constant _Z5 =
0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d;
bytes32 private constant _Z6 =
0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968;
bytes32 private constant _Z7 =
0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83;
bytes32 private constant _Z8 =
0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af;
bytes32 private constant _Z9 =
0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0;
bytes32 private constant _Z10 =
0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5;
bytes32 private constant _Z11 =
0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892;
bytes32 private constant _Z12 =
0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c;
// ---------------------------------------------------------------
// Internal Functions
// ---------------------------------------------------------------
/// @dev Hashes entry `_index` into its leaf:
/// `keccak256(abi.encode(ENTRY_TAG, uint256(_index), pubkey, effStake, uint64 activeFromL1,
/// uint64 exitEffectiveL1, uint64 lastHeartbeatAt, uint64 lastHeartbeatSeq))`.
/// @param _index The entry's index (its bond id).
/// @param _entry The entry.
/// @return The leaf hash.
function leaf(
uint256 _index,
IEtnaStakingRegistry.Entry memory _entry
)
internal
pure
returns (bytes32)
{
return keccak256(
abi.encode(
ENTRY_TAG,
_index,
_entry.pubkey,
_entry.effStake,
_entry.activeFromL1,
_entry.exitEffectiveL1,
_entry.lastHeartbeatAt,
_entry.lastHeartbeatSeq
)
);
}
/// @dev Writes leaf `_index` and its ancestors up to the root level of `_count` leaves, and
/// returns the new root. Appending leaf `n` passes `_count = n + 1`; rewriting an existing
/// leaf passes the current count. Siblings that start at or beyond `_count` hold no leaf and
/// are read as zero hashes without touching storage.
/// @param _tree The tree nodes.
/// @param _count The number of leaves after this write; at least `_index + 1` and at most
/// `CAPACITY`.
/// @param _index The leaf index.
/// @param _leaf The new leaf.
/// @return root_ The root over the first `_count` leaves (see `root`).
function update(
mapping(uint256 node => bytes32) storage _tree,
uint256 _count,
uint256 _index,
bytes32 _leaf
)
internal
returns (bytes32 root_)
{
require(_index < _count && _count <= CAPACITY, LeafIndexOutOfRange());
bytes32 hash = _leaf;
uint256 index = _index;
// Every node from the leaf up to level ceil(log2(_count)), the first level with
// `(_count - 1) >> level == 0`, is rewritten. `_count` is at least 1, and `level` and
// `index` stay below 13 and 4096, so no operation here can overflow or underflow.
unchecked {
uint256 last = _count - 1;
for (uint256 level;; ++level) {
_tree[(level << 32) | index] = hash;
if (last >> level == 0) break;
uint256 siblingIndex = index ^ 1;
bytes32 sibling = (siblingIndex << level) < _count
? _node(_tree, level, siblingIndex)
: zero(level);
hash = index & 1 == 0 ? _hashPair(hash, sibling) : _hashPair(sibling, hash);
index >>= 1;
}
}
root_ = hash;
}
/// @dev Returns the root over the first `_count` leaves: `bytes32(0)` for no leaf, leaf 0
/// for one leaf, otherwise the node at level `ceil(log2(_count))`, index 0. The tree keeps
/// only its current state, so `_count` must be the number of leaves written so far.
/// @param _tree The tree nodes.
/// @param _count The number of leaves written so far, at most `CAPACITY`.
/// @return root_ The root.
function root(
mapping(uint256 node => bytes32) storage _tree,
uint256 _count
)
internal
view
returns (bytes32 root_)
{
require(_count <= CAPACITY, LeafIndexOutOfRange());
if (_count == 0) return 0;
// The root level is ceil(log2(_count)), the first level with `(_count - 1) >> level == 0`;
// `_count` is at least 1 and `level` stays at most 12.
uint256 level;
unchecked {
uint256 last = _count - 1;
while (last >> level != 0) {
++level;
}
}
root_ = _node(_tree, level, 0);
}
/// @dev Returns the zero hash of `_level`: `bytes32(0)` at level 0 and
/// `keccak256(zero(_level - 1) ‖ zero(_level - 1))` above.
/// @param _level The tree level, at most `DEPTH`.
/// @return The precomputed zero hash.
function zero(uint256 _level) internal pure returns (bytes32) {
if (_level == 0) return 0;
if (_level == 1) return _Z1;
if (_level == 2) return _Z2;
if (_level == 3) return _Z3;
if (_level == 4) return _Z4;
if (_level == 5) return _Z5;
if (_level == 6) return _Z6;
if (_level == 7) return _Z7;
if (_level == 8) return _Z8;
if (_level == 9) return _Z9;
if (_level == 10) return _Z10;
if (_level == 11) return _Z11;
if (_level == 12) return _Z12;
revert LevelOutOfRange();
}
// ---------------------------------------------------------------
// Private Functions
// ---------------------------------------------------------------
/// @dev Reads node `(_level, _index)`, substituting the level's zero hash if it was never
/// written.
/// @param _tree The tree nodes.
/// @param _level The node's level.
/// @param _index The node's index within its level.
/// @return node_ The node.
function _node(
mapping(uint256 node => bytes32) storage _tree,
uint256 _level,
uint256 _index
)
private
view
returns (bytes32 node_)
{
node_ = _tree[(_level << 32) | _index];
if (node_ == 0) node_ = zero(_level);
}
/// @dev Hashes two nodes: `keccak256(_left ‖ _right)`.
/// @param _left The left child.
/// @param _right The right child.
/// @return hash_ The parent node.
function _hashPair(bytes32 _left, bytes32 _right) private pure returns (bytes32 hash_) {
assembly ("memory-safe") {
mstore(0x00, _left)
mstore(0x20, _right)
hash_ := keccak256(0x00, 0x40)
}
}
// ---------------------------------------------------------------
// Custom Errors
// ---------------------------------------------------------------
error LeafIndexOutOfRange();
error LevelOutOfRange();
}
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);
}
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/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
}
}
}
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/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
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":"address","name":"_taikoToken","internalType":"address"},{"type":"uint256","name":"_minStake","internalType":"uint256"},{"type":"uint64","name":"_activationDelay","internalType":"uint64"},{"type":"uint64","name":"_exitDelay","internalType":"uint64"},{"type":"uint64","name":"_withdrawalDelay","internalType":"uint64"},{"type":"uint64","name":"_heartbeatWindow","internalType":"uint64"}]},{"type":"error","name":"ACCESS_DENIED","inputs":[]},{"type":"error","name":"AlreadyExited","inputs":[]},{"type":"error","name":"AlreadyWithdrawn","inputs":[]},{"type":"error","name":"ExitAlreadyRequested","inputs":[]},{"type":"error","name":"ExitNotRequested","inputs":[]},{"type":"error","name":"FUNC_NOT_IMPLEMENTED","inputs":[]},{"type":"error","name":"HeartbeatAlreadyRecorded","inputs":[]},{"type":"error","name":"INVALID_PAUSE_STATUS","inputs":[]},{"type":"error","name":"InvalidHeartbeatWindow","inputs":[]},{"type":"error","name":"LeafIndexOutOfRange","inputs":[]},{"type":"error","name":"LevelOutOfRange","inputs":[]},{"type":"error","name":"NotBondOwner","inputs":[]},{"type":"error","name":"PubkeyInUse","inputs":[]},{"type":"error","name":"REENTRANT_CALL","inputs":[]},{"type":"error","name":"RegistryFull","inputs":[]},{"type":"error","name":"StakeTooLow","inputs":[]},{"type":"error","name":"UnknownBond","inputs":[]},{"type":"error","name":"UnknownCheckpoint","inputs":[]},{"type":"error","name":"WithdrawalNotReady","inputs":[]},{"type":"error","name":"ZERO_ADDRESS","inputs":[]},{"type":"error","name":"ZERO_VALUE","inputs":[]},{"type":"error","name":"ZeroPubkey","inputs":[]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"CheckpointWritten","inputs":[{"type":"uint256","name":"index","internalType":"uint256","indexed":true},{"type":"uint64","name":"l1Block","internalType":"uint64","indexed":false},{"type":"uint32","name":"count","internalType":"uint32","indexed":false},{"type":"bytes32","name":"entriesRoot","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"ExitRequested","inputs":[{"type":"uint256","name":"bondId","internalType":"uint256","indexed":true},{"type":"uint64","name":"exitEffectiveL1","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"HeartbeatRecorded","inputs":[{"type":"uint256","name":"bondId","internalType":"uint256","indexed":true},{"type":"uint64","name":"windowStart","internalType":"uint64","indexed":false},{"type":"uint64","name":"seq","internalType":"uint64","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":"Registered","inputs":[{"type":"uint256","name":"bondId","internalType":"uint256","indexed":true},{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"bytes32","name":"pubkey","internalType":"bytes32","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint64","name":"activeFromL1","internalType":"uint64","indexed":false}],"anonymous":false},{"type":"event","name":"StakeWithdrawn","inputs":[{"type":"uint256","name":"bondId","internalType":"uint256","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","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":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_ENTRIES","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"activationDelay","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"bondOwnerOf","inputs":[{"type":"uint256","name":"_bondId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct IEtnaStakingRegistry.Checkpoint","components":[{"type":"uint64","name":"l1Block","internalType":"uint64"},{"type":"uint32","name":"count","internalType":"uint32"},{"type":"bytes32","name":"entriesRoot","internalType":"bytes32"}]}],"name":"checkpointAt","inputs":[{"type":"uint256","name":"_index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkpointCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"entriesRoot","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct IEtnaStakingRegistry.Entry","components":[{"type":"bytes32","name":"pubkey","internalType":"bytes32"},{"type":"uint256","name":"effStake","internalType":"uint256"},{"type":"uint64","name":"activeFromL1","internalType":"uint64"},{"type":"uint64","name":"exitEffectiveL1","internalType":"uint64"},{"type":"uint64","name":"lastHeartbeatAt","internalType":"uint64"},{"type":"uint64","name":"lastHeartbeatSeq","internalType":"uint64"}]}],"name":"entryAt","inputs":[{"type":"uint256","name":"_bondId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"entryCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"exitDelay","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"heartbeat","inputs":[{"type":"uint256","name":"_bondId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"heartbeatWindow","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"impl","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"inNonReentrant","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"init","inputs":[{"type":"address","name":"_owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isWithdrawn","inputs":[{"type":"uint256","name":"_bondId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minStake","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":"nonpayable","outputs":[{"type":"uint256","name":"bondId_","internalType":"uint256"}],"name":"register","inputs":[{"type":"bytes32","name":"_pubkey","internalType":"bytes32"},{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"requestExit","inputs":[{"type":"uint256","name":"_bondId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"resolver","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"taikoToken","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"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[{"type":"uint256","name":"_bondId","internalType":"uint256"},{"type":"address","name":"_to","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint64","name":"","internalType":"uint64"}],"name":"withdrawalDelay","inputs":[]}]
Contract Creation Code
0x61018060405230608052348015610014575f5ffd5b50604051612da2380380612da2833981016040819052610033916101bc565b61003b6100e5565b6001600160a01b0386166100625760405163538ba4f960e01b815260040160405180910390fd5b845f036100825760405163ec73295960e01b815260040160405180910390fd5b806001600160401b03165f036100ab5760405163203d0e2160e11b815260040160405180910390fd5b6001600160a01b0390951660c05260e0939093526001600160401b0391821661010052811661012052908116610140521661016052610233565b5f54610100900460ff16156101505760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff9081161461019f575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160401b03811681146101b7575f5ffd5b919050565b5f5f5f5f5f5f60c087890312156101d1575f5ffd5b86516001600160a01b03811681146101e7575f5ffd5b602088015190965094506101fd604088016101a1565b935061020b606088016101a1565b9250610219608088016101a1565b915061022760a088016101a1565b90509295509295509295565b60805160a05160c05160e05161010051610120516101405161016051612ac76102db5f395f81816104ce0152610dbb01525f81816105f3015261084d01525f81816102cf015261104901525f81816103b1015261150301525f818161037e01526113cf01525f8181610515015281816108c3015261164a01525f61021801525f8181610a5c01528181610a9c01528181610b7e01528181610bbe0152610c350152612ac75ff3fe6080604052600436106101e5575f3560e01c8063721c6513116101085780639c67a3851161009d578063e30c39781161006d578063e30c397814610676578063f2fde38b14610693578063fea4956f146106b2578063ff3617f814610705578063ff9536db14610724575f5ffd5b80639c67a38514610554578063a7ab6961146105e2578063c30184b714610615578063d004f34914610662575f5ffd5b806389418da3116100d857806389418da3146104bd5780638abf6077146104f05780638b68c4a9146105045780638da5cb5b14610537575f5ffd5b8063721c65131461046157806379ba5097146104805780637d4cb964146104945780638456cb59146104a9575f5ffd5b8063375b3c0a1161017e57806352d1902d1161014e57806352d1902d146103fa5780635c975abb1461040e5780636e029ad11461042e578063715018a61461044d575f5ffd5b8063375b3c0a1461036d5780633a8c0786146103a05780633f4ba83a146103d35780634f1ef286146103e7575f5ffd5b80631f618cd2116101b95780631f618cd21461029e57806328388630146102be5780633075db56146103095780633659cfe61461034e575f5ffd5b8062f714ce146101e957806304f3bcec1461020a5780630cbb0f831461025557806319ab453c1461027f575b5f5ffd5b3480156101f4575f5ffd5b50610208610203366004612675565b610774565b005b348015610215575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b348015610260575f5ffd5b505f516020612a0b5f395f51905f52545b60405190815260200161024c565b34801561028a575f5ffd5b5061020861029936600461269f565b610941565b3480156102a9575f5ffd5b505f516020612a725f395f51905f5254610271565b3480156102c9575f5ffd5b506102f17f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160401b03909116815260200161024c565b348015610314575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b604051901515815260200161024c565b348015610359575f5ffd5b5061020861036836600461269f565b610a52565b348015610378575f5ffd5b506102717f000000000000000000000000000000000000000000000000000000000000000081565b3480156103ab575f5ffd5b506102f17f000000000000000000000000000000000000000000000000000000000000000081565b3480156103de575f5ffd5b50610208610b19565b6102086103f53660046126cc565b610b74565b348015610405575f5ffd5b50610271610c29565b348015610419575f5ffd5b5061033e60c954610100900460ff1660021490565b348015610439575f5ffd5b5061020861044836600461278d565b610cda565b348015610458575f5ffd5b50610208610f3b565b34801561046c575f5ffd5b5061020861047b36600461278d565b610f4c565b34801561048b575f5ffd5b50610208611125565b34801561049f575f5ffd5b5061027161100081565b3480156104b4575f5ffd5b5061020861119c565b3480156104c8575f5ffd5b506102f17f000000000000000000000000000000000000000000000000000000000000000081565b3480156104fb575f5ffd5b506102386111f1565b34801561050f575f5ffd5b506102387f000000000000000000000000000000000000000000000000000000000000000081565b348015610542575f5ffd5b506033546001600160a01b0316610238565b34801561055f575f5ffd5b5061057361056e36600461278d565b6111ff565b60405161024c91905f60c08201905082518252602083015160208301526001600160401b0360408401511660408301526001600160401b0360608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015292915050565b3480156105ed575f5ffd5b506102f17f000000000000000000000000000000000000000000000000000000000000000081565b348015610620575f5ffd5b5061033e61062f36600461278d565b5f9081527f46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b8003602052604090205460ff1690565b34801561066d575f5ffd5b506102716112f8565b348015610681575f5ffd5b506065546001600160a01b0316610238565b34801561069e575f5ffd5b506102086106ad36600461269f565b611349565b3480156106bd575f5ffd5b506102386106cc36600461278d565b5f9081527f46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b800260205260409020546001600160a01b031690565b348015610710575f5ffd5b5061027161071f3660046127a4565b6113ba565b34801561072f575f5ffd5b5061074361073e36600461278d565b6116d6565b6040805182516001600160401b0316815260208084015163ffffffff1690820152918101519082015260600161024c565b61077c611788565b61078660026117cd565b80610790816117f3565b5f516020612a725f395f51905f526107a8818561181a565b505f84815260038201602052604090205460ff16156107da57604051636507689f60e01b815260040160405180910390fd5b5f8160010185815481106107f0576107f06127c4565b5f91825260209091206003909102016002810154909150600160401b90046001600160401b031667fffffffffffffffe198101610840576040516306a0786d60e51b815260040160405180910390fd5b6108766001600160401b037f000000000000000000000000000000000000000000000000000000000000000081169083166127ec565b43101561089657604051630f2ca6e760e01b815260040160405180910390fd5b5f8681526003840160205260409020805460ff191660019081179091558201546108ea6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168783611877565b856001600160a01b0316877f459d5aef2c549903c1eeb1736f5728845d5ccf82537ddd5bf8035795eee892638360405161092691815260200190565b60405180910390a3505050505061093d60016117cd565b5050565b5f54610100900460ff161580801561095f57505f54600160ff909116105b806109785750303b15801561097857505f5460ff166001145b6109e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015610a01575f805461ff0019166101001790555b610a0a826118df565b801561093d575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610a9a5760405162461bcd60e51b81526004016109d7906127ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610acc61193d565b6001600160a01b031614610af25760405162461bcd60e51b81526004016109d79061284b565b610afb81611958565b604080515f80825260208201909252610b1691839190611960565b50565b610b21611aca565b610b3560c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a1610b72335f611afb565b565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bbc5760405162461bcd60e51b81526004016109d7906127ff565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610bee61193d565b6001600160a01b031614610c145760405162461bcd60e51b81526004016109d79061284b565b610c1d82611958565b61093d82826001611960565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610cc85760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016109d7565b505f516020612a2b5f395f51905f5290565b610ce2611788565b610cec60026117cd565b5f516020612a725f395f51905f525f610d05828461181a565b90505f826001018481548110610d1d57610d1d6127c4565b5f9182526020918290206040805160c0810182526003909302909101805483526001810154938301939093526002909201546001600160401b0380821693830193909352600160401b8104831660608301819052600160801b820484166080840152600160c01b90910490921660a082015291504310610db057604051631ecb2c4f60e31b815260040160405180910390fd5b5f6001600160401b037f000000000000000000000000000000000000000000000000000000000000000016610de58143612897565b610def91906128b6565b90508160a001516001600160401b03165f1480610e21575081608001516001600160401b0316816001600160401b0316115b610e3e5760405163e6ea457760e01b815260040160405180910390fd5b6001600160401b038116608083015260a082018051610e5c906128cd565b6001600160401b031690526001840180545f919087908110610e8057610e806127c4565b5f91825260209091206002600390920201908101805460a08601516001600160401b03908116600160c01b026001600160c01b03918716600160801b02919091166001600160801b03909216919091171790559050610ee185858886611b03565b60a0830151604080516001600160401b038086168252909216602083015287917fab28e0fde292c29e9611ea6f9fdaadbcd81d52b4abd0b33dd26a4dda32a7ff4e910160405180910390a25050505050610b1660016117cd565b610f43611d66565b610b725f611dc0565b610f54611788565b610f5e60026117cd565b5f516020612a725f395f51905f525f610f77828461181a565b90505f826001018481548110610f8f57610f8f6127c4565b5f9182526020918290206040805160c0810182526003909302909101805483526001810154938301939093526002909201546001600160401b0380821693830193909352600160401b8104831660608301819052600160801b820484166080840152600160c01b909104831660a0830152909250146110215760405163e7f70e6560e01b815260040160405180910390fd5b5f81604001516001600160401b03164311611040578160400151611042565b435b905061106e7f0000000000000000000000000000000000000000000000000000000000000000826128f7565b6001600160401b03166060830181905260018501805487908110611094576110946127c4565b905f5260205f20906003020160020160086101000a8154816001600160401b0302191690836001600160401b031602179055506110d384848785611b03565b60608201516040516001600160401b03909116815285907f60860e2ffac8bccbd94c71a5c5159f1ce9070d2ae7074b64e1e1926a980315349060200160405180910390a250505050610b1660016117cd565b60655433906001600160a01b031681146111935760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016109d7565b610b1681611dc0565b6111a4611dd9565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a1610b72336001611afb565b5f6111fa61193d565b905090565b6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a08101919091525f516020612a0b5f395f51905f52545f516020612a725f395f51905f5290831061126d57604051638301842360e01b815260040160405180910390fd5b806001018381548110611282576112826127c4565b5f9182526020918290206040805160c0810182526003909302909101805483526001810154938301939093526002909201546001600160401b0380821693830193909352600160401b810483166060830152600160801b810483166080830152600160c01b900490911660a08201529392505050565b5f516020612a0b5f395f51905f52545f905f516020612a725f395f51905f5290611343907f46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b800590611e0b565b91505090565b611351611d66565b606580546001600160a01b0383166001600160a01b031990911681179091556113826033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6113c3611788565b6113cd60026117cd565b7f000000000000000000000000000000000000000000000000000000000000000082101561140e57604051631cc3b37b60e01b815260040160405180910390fd5b5f83900361142f57604051634935505f60e01b815260040160405180910390fd5b505f516020612a0b5f395f51905f52545f516020612a725f395f51905f52611000821061146f5760405163d107156760e01b815260040160405180910390fd5b5f84815260048201602052604090205480156114e95743826001016001836114979190612916565b815481106114a7576114a76127c4565b5f918252602090912060039091020160020154600160401b90046001600160401b031611156114e95760405163299d8abf60e11b815260040160405180910390fd5b5f6040518060c001604052808781526020018681526020017f00000000000000000000000000000000000000000000000000000000000000004361152d91906128f7565b6001600160401b03908116825260208083018290525f604080850182905260609485018290526001808a0180548083018255908452848420885160039092020190815587850151818301558783015160029182018054988a015160808b015160a08c01518a16600160c01b026001600160c01b03918b16600160801b02919091166001600160801b03928b16600160401b026fffffffffffffffffffffffffffffffff19909c1694909a1693909317999099179890981696909617959095179095558982529288019091522080546001600160a01b031916331790559091506116179085906127ec565b5f87815260048501602052604090205561163d836116368660016127ec565b8684611b03565b6116726001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333088611e6a565b6040818101518151888152602081018890526001600160401b03909116818301529051339186917f11925f870b078aa29f5ea81f3387261d36c881d5cbfd6f4e605fb1f56ddf78d19181900360600190a35050506116d060016117cd565b92915050565b604080516060810182525f80825260208201819052918101919091525f516020612a725f395f51905f5280548310611721576040516323c87bcd60e21b815260040160405180910390fd5b805f018381548110611735576117356127c4565b5f91825260209182902060408051606081018252600290930290910180546001600160401b038116845263ffffffff600160401b9091041693830193909352600190920154918101919091529392505050565b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff1603610b725760405163dfc60d8560e01b815260040160405180910390fd5b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b6001600160a01b038116610b165760405163538ba4f960e01b815260040160405180910390fd5b600182015480821061183f57604051638301842360e01b815260040160405180910390fd5b5f8281526002840160205260409020546001600160a01b031633146116d0576040516367dad94560e11b815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526118da90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611ea8565b505050565b5f54610100900460ff166119055760405162461bcd60e51b81526004016109d790612929565b61190d611f7b565b61192b6001600160a01b038216156119255781611dc0565b33611dc0565b5060c9805461ff001916610100179055565b5f516020612a2b5f395f51905f52546001600160a01b031690565b610b16611d66565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611993576118da83611fa1565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156119ed575060408051601f3d908101601f191682019092526119ea91810190612974565b60015b611a505760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016109d7565b5f516020612a2b5f395f51905f528114611abe5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016109d7565b506118da83838361203c565b611ade60c954610100900460ff1660021490565b610b725760405163bae6e2a960e01b815260040160405180910390fd5b61093d611d66565b805160208083015160408085015160608087015160808089015160a0808b015187516d45544e415f5245475f454e54525960901b818c01528089018e90529586019a909a52918401969096526001600160401b0393841690830152821660c082015292811660e0840152909316610100808301919091528351808303909101815261012090910190925281519101205f90611ba690600587019086908690612060565b8554909150439085908015801590611bfa57506001600160401b03831688611bcf600184612916565b81548110611bdf57611bdf6127c4565b5f9182526020909120600290910201546001600160401b0316145b15611c5b57611c088161298b565b90505f885f018281548110611c1f57611c1f6127c4565b5f918252602090912060029091020180546bffffffff00000000000000001916600160401b63ffffffff86160217815560010185905550611d0b565b875f016040518060600160405280856001600160401b031681526020018463ffffffff16815260200186815250908060018154018082558091505060019003905f5260205f2090600202015f909190919091505f820151815f015f6101000a8154816001600160401b0302191690836001600160401b031602179055506020820151815f0160086101000a81548163ffffffff021916908363ffffffff1602179055506040820151816001015550505b604080516001600160401b038516815263ffffffff8416602082015290810185905281907f748f355a401d732ac5031aee00cab6561bd9a500aee35b1c624c355d098775169060600160405180910390a25050505050505050565b6033546001600160a01b03163314610b725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109d7565b606580546001600160a01b0319169055610b1681612124565b611ded60c954610100900460ff1660021490565b15610b725760405163bae6e2a960e01b815260040160405180910390fd5b5f611000821115611e2f57604051630231ec4360e31b815260040160405180910390fd5b815f03611e3d57505f6116d0565b5f5f1983015b80821c15611e5657816001019150611e43565b50611e6284825f612175565b949350505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611ea29085906323b872dd60e01b906084016118a3565b50505050565b5f611efc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121a49092919063ffffffff16565b905080515f1480611f1c575080806020019051810190611f1c91906129a0565b6118da5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109d7565b5f54610100900460ff16610b725760405162461bcd60e51b81526004016109d790612929565b6001600160a01b0381163b61200e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016109d7565b5f516020612a2b5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b612045836121b2565b5f825111806120515750805b156118da57611ea283836121f1565b5f838310801561207257506110008411155b61208f57604051630231ec4360e31b815260040160405180910390fd5b81835f1986015f5b602081811b84175f908152908a90526040902084905581811c1561211757600183185f81831b8a116120d1576120cc83612216565b6120dc565b6120dc8b8484612175565b905060018516156120f9575f818152602087905260409020612107565b5f8681526020829052604090205b95505050600192831c9201612097565b5091979650505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b602082811b82175f9081529084905260408120549081900361219d5761219a83612216565b90505b9392505050565b606061219a84845f85612472565b6121bb81611fa1565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b606061219d8383604051806060016040528060278152602001612a4b60279139612549565b5f815f0361222557505f919050565b8160010361225457507fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5919050565b8160020361228357507fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30919050565b816003036122b257507f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85919050565b816004036122e157507fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344919050565b8160050361231057507f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d919050565b8160060361233f57507f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968919050565b8160070361236e57507fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83919050565b8160080361239d57507f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af919050565b816009036123cc57507fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0919050565b81600a036123fb57507ff9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5919050565b81600b0361242a57507ff8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892919050565b81600c0361245957507f3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c919050565b6040516336b62db160e21b815260040160405180910390fd5b6060824710156124d35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109d7565b5f5f866001600160a01b031685876040516124ee91906129bf565b5f6040518083038185875af1925050503d805f8114612528576040519150601f19603f3d011682016040523d82523d5f602084013e61252d565b606091505b509150915061253e878383876125bd565b979650505050505050565b60605f5f856001600160a01b03168560405161256591906129bf565b5f60405180830381855af49150503d805f811461259d576040519150601f19603f3d011682016040523d82523d5f602084013e6125a2565b606091505b50915091506125b3868383876125bd565b9695505050505050565b6060831561262b5782515f03612624576001600160a01b0385163b6126245760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109d7565b5081611e62565b611e6283838151156126405781518083602001fd5b8060405162461bcd60e51b81526004016109d791906129d5565b80356001600160a01b0381168114612670575f5ffd5b919050565b5f5f60408385031215612686575f5ffd5b823591506126966020840161265a565b90509250929050565b5f602082840312156126af575f5ffd5b61219d8261265a565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156126dd575f5ffd5b6126e68361265a565b915060208301356001600160401b03811115612700575f5ffd5b8301601f81018513612710575f5ffd5b80356001600160401b03811115612729576127296126b8565b604051601f8201601f19908116603f011681016001600160401b0381118282101715612757576127576126b8565b60405281815282820160200187101561276e575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f6020828403121561279d575f5ffd5b5035919050565b5f5f604083850312156127b5575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156116d0576116d06127d8565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b5f826128b157634e487b7160e01b5f52601260045260245ffd5b500490565b80820281158282048414176116d0576116d06127d8565b5f6001600160401b0382166001600160401b0381036128ee576128ee6127d8565b60010192915050565b6001600160401b0381811683821601908111156116d0576116d06127d8565b818103818111156116d0576116d06127d8565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f60208284031215612984575f5ffd5b5051919050565b5f81612999576129996127d8565b505f190190565b5f602082840312156129b0575f5ffd5b8151801515811461219d575f5ffd5b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b8001360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c656446e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b8000a264697066735822122030c147be1587404dc98725ed988f26571a7f40ca3b144f5e4478d5ea1ca8bfb664736f6c634300081e0033000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af00000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000007fffffffffffffff
Deployed ByteCode
0x6080604052600436106101e5575f3560e01c8063721c6513116101085780639c67a3851161009d578063e30c39781161006d578063e30c397814610676578063f2fde38b14610693578063fea4956f146106b2578063ff3617f814610705578063ff9536db14610724575f5ffd5b80639c67a38514610554578063a7ab6961146105e2578063c30184b714610615578063d004f34914610662575f5ffd5b806389418da3116100d857806389418da3146104bd5780638abf6077146104f05780638b68c4a9146105045780638da5cb5b14610537575f5ffd5b8063721c65131461046157806379ba5097146104805780637d4cb964146104945780638456cb59146104a9575f5ffd5b8063375b3c0a1161017e57806352d1902d1161014e57806352d1902d146103fa5780635c975abb1461040e5780636e029ad11461042e578063715018a61461044d575f5ffd5b8063375b3c0a1461036d5780633a8c0786146103a05780633f4ba83a146103d35780634f1ef286146103e7575f5ffd5b80631f618cd2116101b95780631f618cd21461029e57806328388630146102be5780633075db56146103095780633659cfe61461034e575f5ffd5b8062f714ce146101e957806304f3bcec1461020a5780630cbb0f831461025557806319ab453c1461027f575b5f5ffd5b3480156101f4575f5ffd5b50610208610203366004612675565b610774565b005b348015610215575f5ffd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020015b60405180910390f35b348015610260575f5ffd5b505f516020612a0b5f395f51905f52545b60405190815260200161024c565b34801561028a575f5ffd5b5061020861029936600461269f565b610941565b3480156102a9575f5ffd5b505f516020612a725f395f51905f5254610271565b3480156102c9575f5ffd5b506102f17f000000000000000000000000000000000000000000000000000000000000004081565b6040516001600160401b03909116815260200161024c565b348015610314575f5ffd5b5060027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff16145b604051901515815260200161024c565b348015610359575f5ffd5b5061020861036836600461269f565b610a52565b348015610378575f5ffd5b506102717f0000000000000000000000000000000000000000000000000de0b6b3a764000081565b3480156103ab575f5ffd5b506102f17f000000000000000000000000000000000000000000000000000000000000000081565b3480156103de575f5ffd5b50610208610b19565b6102086103f53660046126cc565b610b74565b348015610405575f5ffd5b50610271610c29565b348015610419575f5ffd5b5061033e60c954610100900460ff1660021490565b348015610439575f5ffd5b5061020861044836600461278d565b610cda565b348015610458575f5ffd5b50610208610f3b565b34801561046c575f5ffd5b5061020861047b36600461278d565b610f4c565b34801561048b575f5ffd5b50610208611125565b34801561049f575f5ffd5b5061027161100081565b3480156104b4575f5ffd5b5061020861119c565b3480156104c8575f5ffd5b506102f17f0000000000000000000000000000000000000000000000007fffffffffffffff81565b3480156104fb575f5ffd5b506102386111f1565b34801561050f575f5ffd5b506102387f000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af081565b348015610542575f5ffd5b506033546001600160a01b0316610238565b34801561055f575f5ffd5b5061057361056e36600461278d565b6111ff565b60405161024c91905f60c08201905082518252602083015160208301526001600160401b0360408401511660408301526001600160401b0360608401511660608301526001600160401b0360808401511660808301526001600160401b0360a08401511660a083015292915050565b3480156105ed575f5ffd5b506102f17f000000000000000000000000000000000000000000000000000000000000004081565b348015610620575f5ffd5b5061033e61062f36600461278d565b5f9081527f46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b8003602052604090205460ff1690565b34801561066d575f5ffd5b506102716112f8565b348015610681575f5ffd5b506065546001600160a01b0316610238565b34801561069e575f5ffd5b506102086106ad36600461269f565b611349565b3480156106bd575f5ffd5b506102386106cc36600461278d565b5f9081527f46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b800260205260409020546001600160a01b031690565b348015610710575f5ffd5b5061027161071f3660046127a4565b6113ba565b34801561072f575f5ffd5b5061074361073e36600461278d565b6116d6565b6040805182516001600160401b0316815260208084015163ffffffff1690820152918101519082015260600161024c565b61077c611788565b61078660026117cd565b80610790816117f3565b5f516020612a725f395f51905f526107a8818561181a565b505f84815260038201602052604090205460ff16156107da57604051636507689f60e01b815260040160405180910390fd5b5f8160010185815481106107f0576107f06127c4565b5f91825260209091206003909102016002810154909150600160401b90046001600160401b031667fffffffffffffffe198101610840576040516306a0786d60e51b815260040160405180910390fd5b6108766001600160401b037f000000000000000000000000000000000000000000000000000000000000004081169083166127ec565b43101561089657604051630f2ca6e760e01b815260040160405180910390fd5b5f8681526003840160205260409020805460ff191660019081179091558201546108ea6001600160a01b037f000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af0168783611877565b856001600160a01b0316877f459d5aef2c549903c1eeb1736f5728845d5ccf82537ddd5bf8035795eee892638360405161092691815260200190565b60405180910390a3505050505061093d60016117cd565b5050565b5f54610100900460ff161580801561095f57505f54600160ff909116105b806109785750303b15801561097857505f5460ff166001145b6109e05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015610a01575f805461ff0019166101001790555b610a0a826118df565b801561093d575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b037f000000000000000000000000ebb0da61818f639f460f67940eb269b36d1f104e163003610a9a5760405162461bcd60e51b81526004016109d7906127ff565b7f000000000000000000000000ebb0da61818f639f460f67940eb269b36d1f104e6001600160a01b0316610acc61193d565b6001600160a01b031614610af25760405162461bcd60e51b81526004016109d79061284b565b610afb81611958565b604080515f80825260208201909252610b1691839190611960565b50565b610b21611aca565b610b3560c9805461ff001916610100179055565b6040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9060200160405180910390a1610b72335f611afb565b565b6001600160a01b037f000000000000000000000000ebb0da61818f639f460f67940eb269b36d1f104e163003610bbc5760405162461bcd60e51b81526004016109d7906127ff565b7f000000000000000000000000ebb0da61818f639f460f67940eb269b36d1f104e6001600160a01b0316610bee61193d565b6001600160a01b031614610c145760405162461bcd60e51b81526004016109d79061284b565b610c1d82611958565b61093d82826001611960565b5f306001600160a01b037f000000000000000000000000ebb0da61818f639f460f67940eb269b36d1f104e1614610cc85760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016109d7565b505f516020612a2b5f395f51905f5290565b610ce2611788565b610cec60026117cd565b5f516020612a725f395f51905f525f610d05828461181a565b90505f826001018481548110610d1d57610d1d6127c4565b5f9182526020918290206040805160c0810182526003909302909101805483526001810154938301939093526002909201546001600160401b0380821693830193909352600160401b8104831660608301819052600160801b820484166080840152600160c01b90910490921660a082015291504310610db057604051631ecb2c4f60e31b815260040160405180910390fd5b5f6001600160401b037f0000000000000000000000000000000000000000000000007fffffffffffffff16610de58143612897565b610def91906128b6565b90508160a001516001600160401b03165f1480610e21575081608001516001600160401b0316816001600160401b0316115b610e3e5760405163e6ea457760e01b815260040160405180910390fd5b6001600160401b038116608083015260a082018051610e5c906128cd565b6001600160401b031690526001840180545f919087908110610e8057610e806127c4565b5f91825260209091206002600390920201908101805460a08601516001600160401b03908116600160c01b026001600160c01b03918716600160801b02919091166001600160801b03909216919091171790559050610ee185858886611b03565b60a0830151604080516001600160401b038086168252909216602083015287917fab28e0fde292c29e9611ea6f9fdaadbcd81d52b4abd0b33dd26a4dda32a7ff4e910160405180910390a25050505050610b1660016117cd565b610f43611d66565b610b725f611dc0565b610f54611788565b610f5e60026117cd565b5f516020612a725f395f51905f525f610f77828461181a565b90505f826001018481548110610f8f57610f8f6127c4565b5f9182526020918290206040805160c0810182526003909302909101805483526001810154938301939093526002909201546001600160401b0380821693830193909352600160401b8104831660608301819052600160801b820484166080840152600160c01b909104831660a0830152909250146110215760405163e7f70e6560e01b815260040160405180910390fd5b5f81604001516001600160401b03164311611040578160400151611042565b435b905061106e7f0000000000000000000000000000000000000000000000000000000000000040826128f7565b6001600160401b03166060830181905260018501805487908110611094576110946127c4565b905f5260205f20906003020160020160086101000a8154816001600160401b0302191690836001600160401b031602179055506110d384848785611b03565b60608201516040516001600160401b03909116815285907f60860e2ffac8bccbd94c71a5c5159f1ce9070d2ae7074b64e1e1926a980315349060200160405180910390a250505050610b1660016117cd565b60655433906001600160a01b031681146111935760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016109d7565b610b1681611dc0565b6111a4611dd9565b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589060200160405180910390a1610b72336001611afb565b5f6111fa61193d565b905090565b6040805160c0810182525f80825260208201819052918101829052606081018290526080810182905260a08101919091525f516020612a0b5f395f51905f52545f516020612a725f395f51905f5290831061126d57604051638301842360e01b815260040160405180910390fd5b806001018381548110611282576112826127c4565b5f9182526020918290206040805160c0810182526003909302909101805483526001810154938301939093526002909201546001600160401b0380821693830193909352600160401b810483166060830152600160801b810483166080830152600160c01b900490911660a08201529392505050565b5f516020612a0b5f395f51905f52545f905f516020612a725f395f51905f5290611343907f46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b800590611e0b565b91505090565b611351611d66565b606580546001600160a01b0383166001600160a01b031990911681179091556113826033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6113c3611788565b6113cd60026117cd565b7f0000000000000000000000000000000000000000000000000de0b6b3a764000082101561140e57604051631cc3b37b60e01b815260040160405180910390fd5b5f83900361142f57604051634935505f60e01b815260040160405180910390fd5b505f516020612a0b5f395f51905f52545f516020612a725f395f51905f52611000821061146f5760405163d107156760e01b815260040160405180910390fd5b5f84815260048201602052604090205480156114e95743826001016001836114979190612916565b815481106114a7576114a76127c4565b5f918252602090912060039091020160020154600160401b90046001600160401b031611156114e95760405163299d8abf60e11b815260040160405180910390fd5b5f6040518060c001604052808781526020018681526020017f00000000000000000000000000000000000000000000000000000000000000004361152d91906128f7565b6001600160401b03908116825260208083018290525f604080850182905260609485018290526001808a0180548083018255908452848420885160039092020190815587850151818301558783015160029182018054988a015160808b015160a08c01518a16600160c01b026001600160c01b03918b16600160801b02919091166001600160801b03928b16600160401b026fffffffffffffffffffffffffffffffff19909c1694909a1693909317999099179890981696909617959095179095558982529288019091522080546001600160a01b031916331790559091506116179085906127ec565b5f87815260048501602052604090205561163d836116368660016127ec565b8684611b03565b6116726001600160a01b037f000000000000000000000000f4d761f2e88e7d572aa74feb135b7cdafd727af016333088611e6a565b6040818101518151888152602081018890526001600160401b03909116818301529051339186917f11925f870b078aa29f5ea81f3387261d36c881d5cbfd6f4e605fb1f56ddf78d19181900360600190a35050506116d060016117cd565b92915050565b604080516060810182525f80825260208201819052918101919091525f516020612a725f395f51905f5280548310611721576040516323c87bcd60e21b815260040160405180910390fd5b805f018381548110611735576117356127c4565b5f91825260209182902060408051606081018252600290930290910180546001600160401b038116845263ffffffff600160401b9091041693830193909352600190920154918101919091529392505050565b60027fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c60ff1603610b725760405163dfc60d8560e01b815260040160405180910390fd5b807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b6001600160a01b038116610b165760405163538ba4f960e01b815260040160405180910390fd5b600182015480821061183f57604051638301842360e01b815260040160405180910390fd5b5f8281526002840160205260409020546001600160a01b031633146116d0576040516367dad94560e11b815260040160405180910390fd5b6040516001600160a01b0383166024820152604481018290526118da90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611ea8565b505050565b5f54610100900460ff166119055760405162461bcd60e51b81526004016109d790612929565b61190d611f7b565b61192b6001600160a01b038216156119255781611dc0565b33611dc0565b5060c9805461ff001916610100179055565b5f516020612a2b5f395f51905f52546001600160a01b031690565b610b16611d66565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611993576118da83611fa1565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156119ed575060408051601f3d908101601f191682019092526119ea91810190612974565b60015b611a505760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016109d7565b5f516020612a2b5f395f51905f528114611abe5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016109d7565b506118da83838361203c565b611ade60c954610100900460ff1660021490565b610b725760405163bae6e2a960e01b815260040160405180910390fd5b61093d611d66565b805160208083015160408085015160608087015160808089015160a0808b015187516d45544e415f5245475f454e54525960901b818c01528089018e90529586019a909a52918401969096526001600160401b0393841690830152821660c082015292811660e0840152909316610100808301919091528351808303909101815261012090910190925281519101205f90611ba690600587019086908690612060565b8554909150439085908015801590611bfa57506001600160401b03831688611bcf600184612916565b81548110611bdf57611bdf6127c4565b5f9182526020909120600290910201546001600160401b0316145b15611c5b57611c088161298b565b90505f885f018281548110611c1f57611c1f6127c4565b5f918252602090912060029091020180546bffffffff00000000000000001916600160401b63ffffffff86160217815560010185905550611d0b565b875f016040518060600160405280856001600160401b031681526020018463ffffffff16815260200186815250908060018154018082558091505060019003905f5260205f2090600202015f909190919091505f820151815f015f6101000a8154816001600160401b0302191690836001600160401b031602179055506020820151815f0160086101000a81548163ffffffff021916908363ffffffff1602179055506040820151816001015550505b604080516001600160401b038516815263ffffffff8416602082015290810185905281907f748f355a401d732ac5031aee00cab6561bd9a500aee35b1c624c355d098775169060600160405180910390a25050505050505050565b6033546001600160a01b03163314610b725760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016109d7565b606580546001600160a01b0319169055610b1681612124565b611ded60c954610100900460ff1660021490565b15610b725760405163bae6e2a960e01b815260040160405180910390fd5b5f611000821115611e2f57604051630231ec4360e31b815260040160405180910390fd5b815f03611e3d57505f6116d0565b5f5f1983015b80821c15611e5657816001019150611e43565b50611e6284825f612175565b949350505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611ea29085906323b872dd60e01b906084016118a3565b50505050565b5f611efc826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121a49092919063ffffffff16565b905080515f1480611f1c575080806020019051810190611f1c91906129a0565b6118da5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016109d7565b5f54610100900460ff16610b725760405162461bcd60e51b81526004016109d790612929565b6001600160a01b0381163b61200e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016109d7565b5f516020612a2b5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b612045836121b2565b5f825111806120515750805b156118da57611ea283836121f1565b5f838310801561207257506110008411155b61208f57604051630231ec4360e31b815260040160405180910390fd5b81835f1986015f5b602081811b84175f908152908a90526040902084905581811c1561211757600183185f81831b8a116120d1576120cc83612216565b6120dc565b6120dc8b8484612175565b905060018516156120f9575f818152602087905260409020612107565b5f8681526020829052604090205b95505050600192831c9201612097565b5091979650505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b602082811b82175f9081529084905260408120549081900361219d5761219a83612216565b90505b9392505050565b606061219a84845f85612472565b6121bb81611fa1565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b606061219d8383604051806060016040528060278152602001612a4b60279139612549565b5f815f0361222557505f919050565b8160010361225457507fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5919050565b8160020361228357507fb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30919050565b816003036122b257507f21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85919050565b816004036122e157507fe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344919050565b8160050361231057507f0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d919050565b8160060361233f57507f887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968919050565b8160070361236e57507fffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83919050565b8160080361239d57507f9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af919050565b816009036123cc57507fcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0919050565b81600a036123fb57507ff9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5919050565b81600b0361242a57507ff8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892919050565b81600c0361245957507f3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c919050565b6040516336b62db160e21b815260040160405180910390fd5b6060824710156124d35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016109d7565b5f5f866001600160a01b031685876040516124ee91906129bf565b5f6040518083038185875af1925050503d805f8114612528576040519150601f19603f3d011682016040523d82523d5f602084013e61252d565b606091505b509150915061253e878383876125bd565b979650505050505050565b60605f5f856001600160a01b03168560405161256591906129bf565b5f60405180830381855af49150503d805f811461259d576040519150601f19603f3d011682016040523d82523d5f602084013e6125a2565b606091505b50915091506125b3868383876125bd565b9695505050505050565b6060831561262b5782515f03612624576001600160a01b0385163b6126245760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016109d7565b5081611e62565b611e6283838151156126405781518083602001fd5b8060405162461bcd60e51b81526004016109d791906129d5565b80356001600160a01b0381168114612670575f5ffd5b919050565b5f5f60408385031215612686575f5ffd5b823591506126966020840161265a565b90509250929050565b5f602082840312156126af575f5ffd5b61219d8261265a565b634e487b7160e01b5f52604160045260245ffd5b5f5f604083850312156126dd575f5ffd5b6126e68361265a565b915060208301356001600160401b03811115612700575f5ffd5b8301601f81018513612710575f5ffd5b80356001600160401b03811115612729576127296126b8565b604051601f8201601f19908116603f011681016001600160401b0381118282101715612757576127576126b8565b60405281815282820160200187101561276e575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f6020828403121561279d575f5ffd5b5035919050565b5f5f604083850312156127b5575f5ffd5b50508035926020909101359150565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156116d0576116d06127d8565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b5f826128b157634e487b7160e01b5f52601260045260245ffd5b500490565b80820281158282048414176116d0576116d06127d8565b5f6001600160401b0382166001600160401b0381036128ee576128ee6127d8565b60010192915050565b6001600160401b0381811683821601908111156116d0576116d06127d8565b818103818111156116d0576116d06127d8565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f60208284031215612984575f5ffd5b5051919050565b5f81612999576129996127d8565b505f190190565b5f602082840312156129b0575f5ffd5b8151801515811461219d575f5ffd5b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f8301168401019150509291505056fe46e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b8001360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c656446e4e2fea4a7d0ac18aca03baa3a1f64e1be04ec23c1ca0c7b901af7b59b8000a264697066735822122030c147be1587404dc98725ed988f26571a7f40ca3b144f5e4478d5ea1ca8bfb664736f6c634300081e0033