Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
TaikoL1Hekla
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./TaikoL1.sol"; /// @title TaikoL1Hekla /// @dev Labeled in AddressResolver as "taiko" /// @custom:security-contact [email protected] contract TaikoL1Hekla is TaikoL1 { /// @inheritdoc ITaikoL1 function getConfig() public pure override returns (TaikoData.Config memory) { return TaikoData.Config({ chainId: LibNetwork.TAIKO_HEKLA, blockMaxProposals: 324_000, // Never change this value as ring buffer is being reused!!! blockRingBufferSize: 324_512, // Never change this value as ring buffer is being // reused!!! maxBlocksToVerify: 16, blockMaxGasLimit: 240_000_000, livenessBond: 125e18, // 125 Taiko token stateRootSyncInternal: 16, checkEOAForCalldataDA: true }); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../common/EssentialContract.sol"; import "./libs/LibProposing.sol"; import "./libs/LibProving.sol"; import "./libs/LibVerifying.sol"; import "./ITaikoL1.sol"; /// @title TaikoL1 /// @notice This contract serves as the "base layer contract" of the Taiko protocol, providing /// functionalities for proposing, proving, and verifying blocks. The term "base layer contract" /// means that although this is usually deployed on L1, it can also be deployed on L2s to create /// L3 "inception layers". The contract also handles the deposit and withdrawal of Taiko tokens /// and Ether. Additionally, this contract doesn't hold any Ether. Ether deposited to L2 are held /// by the Bridge contract. /// @dev Labeled in AddressResolver as "taiko" /// @custom:security-contact [email protected] contract TaikoL1 is EssentialContract, ITaikoL1 { /// @notice The TaikoL1 state. TaikoData.State public state; uint256[50] private __gap; /// @notice Emitted when some state variable values changed. /// @dev This event is currently used by Taiko node/client for block proposal/proving. /// @param slotB The SlotB data structure. event StateVariablesUpdated(TaikoData.SlotB slotB); error L1_RECEIVE_DISABLED(); modifier whenProvingNotPaused() { if (state.slotB.provingPaused) revert LibProving.L1_PROVING_PAUSED(); _; } modifier emitEventForClient() { _; emit StateVariablesUpdated(state.slotB); } /// @dev Allows for receiving Ether from Hooks receive() external payable { if (!inNonReentrant()) revert L1_RECEIVE_DISABLED(); } /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _addressManager The address of the {AddressManager} contract. /// @param _genesisBlockHash The block hash of the genesis block. /// @param _toPause true to pause the contract by default. function init( address _owner, address _addressManager, bytes32 _genesisBlockHash, bool _toPause ) external initializer { __Essential_init(_owner, _addressManager); LibUtils.init(state, _genesisBlockHash); if (_toPause) _pause(); } function init2() external onlyOwner reinitializer(2) { // reset some previously used slots for future reuse state.slotB.__reservedB1 = 0; state.slotB.__reservedB2 = 0; state.slotB.__reservedB3 = 0; state.__reserve1 = 0; } /// @inheritdoc ITaikoL1 function proposeBlock( bytes calldata _params, bytes calldata _txList ) external payable whenNotPaused nonReentrant emitEventForClient returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_) { TaikoData.Config memory config = getConfig(); (meta_, deposits_) = LibProposing.proposeBlock(state, config, this, _params, _txList); if (LibUtils.shouldVerifyBlocks(config, meta_.id, true) && !state.slotB.provingPaused) { LibVerifying.verifyBlocks(state, config, this, config.maxBlocksToVerify); } } /// @inheritdoc ITaikoL1 function proveBlock( uint64 _blockId, bytes calldata _input ) external whenNotPaused whenProvingNotPaused nonReentrant emitEventForClient { TaikoData.Config memory config = getConfig(); LibProving.proveBlock(state, config, this, _blockId, _input); if (LibUtils.shouldVerifyBlocks(config, _blockId, false)) { LibVerifying.verifyBlocks(state, config, this, config.maxBlocksToVerify); } } /// @inheritdoc ITaikoL1 function verifyBlocks( uint64 _maxBlocksToVerify ) external whenNotPaused whenProvingNotPaused nonReentrant emitEventForClient { LibVerifying.verifyBlocks(state, getConfig(), this, _maxBlocksToVerify); } /// @inheritdoc ITaikoL1 function pauseProving(bool _pause) external { _authorizePause(msg.sender, _pause); LibProving.pauseProving(state, _pause); } /// @inheritdoc ITaikoL1 function depositBond(uint256 _amount) external whenNotPaused { LibBonds.depositBond(state, this, _amount); } /// @inheritdoc ITaikoL1 function withdrawBond(uint256 _amount) external whenNotPaused { LibBonds.withdrawBond(state, this, _amount); } /// @notice Gets the current bond balance of a given address. /// @return The current bond balance. function bondBalanceOf(address _user) external view returns (uint256) { return LibBonds.bondBalanceOf(state, _user); } /// @inheritdoc ITaikoL1 function getVerifiedBlockProver(uint64 _blockId) external view returns (address prover_) { return LibVerifying.getVerifiedBlockProver(state, getConfig(), _blockId); } /// @notice Gets the details of a block. /// @param _blockId Index of the block. /// @return blk_ The block. function getBlock(uint64 _blockId) external view returns (TaikoData.Block memory blk_) { (blk_,) = LibUtils.getBlock(state, getConfig(), _blockId); } /// @notice Gets the state transition for a specific block. /// @param _blockId Index of the block. /// @param _parentHash Parent hash of the block. /// @return The state transition data of the block. function getTransition( uint64 _blockId, bytes32 _parentHash ) external view returns (TaikoData.TransitionState memory) { return LibUtils.getTransition(state, getConfig(), _blockId, _parentHash); } /// @notice Gets the state transition for a specific block. /// @param _blockId Index of the block. /// @param _tid The transition id. /// @return The state transition data of the block. function getTransition( uint64 _blockId, uint32 _tid ) external view returns (TaikoData.TransitionState memory) { return LibUtils.getTransition(state, getConfig(), _blockId, _tid); } /// @notice Returns information about the last verified block. /// @return blockId_ The last verified block's ID. /// @return blockHash_ The last verified block's blockHash. /// @return stateRoot_ The last verified block's stateRoot. function getLastVerifiedBlock() external view returns (uint64 blockId_, bytes32 blockHash_, bytes32 stateRoot_) { blockId_ = state.slotB.lastVerifiedBlockId; (blockHash_, stateRoot_) = LibUtils.getBlockInfo(state, getConfig(), blockId_); } /// @notice Returns information about the last synchronized block. /// @return blockId_ The last verified block's ID. /// @return blockHash_ The last verified block's blockHash. /// @return stateRoot_ The last verified block's stateRoot. function getLastSyncedBlock() external view returns (uint64 blockId_, bytes32 blockHash_, bytes32 stateRoot_) { blockId_ = state.slotA.lastSyncedBlockId; (blockHash_, stateRoot_) = LibUtils.getBlockInfo(state, getConfig(), blockId_); } /// @notice Gets the state variables of the TaikoL1 contract. /// @dev This method can be deleted once node/client stops using it. /// @return State variables stored at SlotA. /// @return State variables stored at SlotB. function getStateVariables() external view returns (TaikoData.SlotA memory, TaikoData.SlotB memory) { return (state.slotA, state.slotB); } /// @inheritdoc EssentialContract function unpause() public override { super.unpause(); // permission checked inside state.slotB.lastUnpausedAt = uint64(block.timestamp); } /// @inheritdoc ITaikoL1 function getConfig() public pure virtual override returns (TaikoData.Config memory) { // All hard-coded configurations: // - treasury: the actual TaikoL2 address. // - anchorGasLimit: 250_000 (based on internal devnet, its ~220_000 // after 256 L2 blocks) return TaikoData.Config({ chainId: LibNetwork.TAIKO_MAINNET, // If we have 1 block per 12 seconds, then each day there will be 86400/12=7200 blocks. // We therefore use 7200 as the base unit to configure blockMaxProposals and // blockRingBufferSize. blockMaxProposals: 324_000, // = 7200 * 45 // We give 7200 * 5 = 36000 slots for verifeid blocks in case third party apps will use // their data. blockRingBufferSize: 360_000, // = 7200 * 50 maxBlocksToVerify: 16, // This value is set based on `gasTargetPerL1Block = 15_000_000 * 4` in TaikoL2. // We use 8x rather than 4x here to handle the scenario where the average number of // Taiko blocks proposed per Ethereum block is smaller than 1. // There is 250_000 additional gas for the anchor tx. Therefore, on explorers, you'll // read Taiko's gas limit to be 240_250_000. blockMaxGasLimit: 240_000_000, livenessBond: 125e18, // 125 Taiko token stateRootSyncInternal: 16, checkEOAForCalldataDA: true }); } /// @dev chain_pauser is supposed to be a cold wallet. function _authorizePause( address, bool ) internal view virtual override onlyFromOwnerOrNamed(LibStrings.B_CHAIN_WATCHDOG) { } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import "./AddressResolver.sol"; import "../libs/LibNetwork.sol"; /// @title EssentialContract /// @custom:security-contact [email protected] abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, AddressResolver { uint8 private constant _FALSE = 1; uint8 private constant _TRUE = 2; /// @dev The slot in transient storage of the reentry lock. /// This is the result of keccak256("ownerUUPS.reentry_slot") plus 1. The addition aims to /// prevent hash collisions with slots defined in EIP-1967, where slots are derived by /// keccak256("something") - 1, and with slots in SignalService, calculated directly with /// keccak256("something"). bytes32 private constant _REENTRY_SLOT = 0xa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b; /// @dev Slot 1. uint8 private __reentry; uint8 private __paused; uint64 public lastUnpausedAt; uint256[49] private __gap; /// @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 ZERO_ADDRESS(); error ZERO_VALUE(); /// @dev Modifier that ensures the caller is the owner or resolved address of a given name. /// @param _name The name to check against. modifier onlyFromOwnerOrNamed(bytes32 _name) { if (msg.sender != owner() && msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); _; } modifier notImplemented() { revert FUNC_NOT_IMPLEMENTED(); _; } modifier nonReentrant() { if (_loadReentryLock() == _TRUE) revert REENTRANT_CALL(); _storeReentryLock(_TRUE); _; _storeReentryLock(_FALSE); } modifier whenPaused() { if (!paused()) revert INVALID_PAUSE_STATUS(); _; } modifier whenNotPaused() { if (paused()) revert INVALID_PAUSE_STATUS(); _; } modifier nonZeroAddr(address _addr) { if (_addr == address(0)) revert ZERO_ADDRESS(); _; } modifier nonZeroValue(bytes32 _value) { if (_value == 0) revert ZERO_VALUE(); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @notice Pauses the contract. function pause() public virtual { _pause(); // We call the authorize function here to avoid: // Warning (5740): Unreachable code. _authorizePause(msg.sender, true); } /// @notice Unpauses the contract. function unpause() public virtual { _unpause(); // 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 returns (bool) { return __paused == _TRUE; } function inNonReentrant() public view returns (bool) { return _loadReentryLock() == _TRUE; } /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _addressManager The address of the {AddressManager} contract. function __Essential_init( address _owner, address _addressManager ) internal nonZeroAddr(_addressManager) { __Essential_init(_owner); __AddressResolver_init(_addressManager); } function __Essential_init(address _owner) internal virtual onlyInitializing { __Context_init(); _transferOwnership(_owner == address(0) ? msg.sender : _owner); __paused = _FALSE; } function _pause() internal whenNotPaused { __paused = _TRUE; emit Paused(msg.sender); } function _unpause() internal whenPaused { __paused = _FALSE; lastUnpausedAt = uint64(block.timestamp); emit Unpaused(msg.sender); } function _authorizeUpgrade(address) internal virtual override onlyOwner { } function _authorizePause(address, bool) internal virtual onlyOwner { } // Stores the reentry lock function _storeReentryLock(uint8 _reentry) internal virtual { if (LibNetwork.isDencunSupported(block.chainid)) { assembly { tstore(_REENTRY_SLOT, _reentry) } } else { __reentry = _reentry; } } // Loads the reentry lock function _loadReentryLock() internal view virtual returns (uint8 reentry_) { if (LibNetwork.isDencunSupported(block.chainid)) { assembly { reentry_ := tload(_REENTRY_SLOT) } } else { reentry_ = __reentry; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "../../libs/LibAddress.sol"; import "../../libs/LibNetwork.sol"; import "./LibBonds.sol"; import "./LibUtils.sol"; /// @title LibProposing /// @notice A library for handling block proposals in the Taiko protocol. /// @custom:security-contact [email protected] library LibProposing { using LibAddress for address; // = keccak256(abi.encode(new TaikoData.EthDeposit[](0))) bytes32 private constant _EMPTY_ETH_DEPOSIT_HASH = 0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd; struct Local { TaikoData.SlotB b; TaikoData.BlockParams params; bytes32 parentMetaHash; } /// @notice Emitted when a block is proposed. /// @param blockId The ID of the proposed block. /// @param assignedProver The address of the assigned prover. /// @param livenessBond The liveness bond of the proposed block. /// @param meta The metadata of the proposed block. /// @param depositsProcessed The EthDeposit array about processed deposits in this proposed /// block. event BlockProposed( uint256 indexed blockId, address indexed assignedProver, uint96 livenessBond, TaikoData.BlockMetadata meta, TaikoData.EthDeposit[] depositsProcessed ); /// @notice Emitted when a block's txList is in the calldata. /// @param blockId The ID of the proposed block. /// @param txList The txList. event CalldataTxList(uint256 indexed blockId, bytes txList); error L1_BLOB_NOT_AVAILABLE(); error L1_BLOB_NOT_FOUND(); error L1_INVALID_SIG(); error L1_LIVENESS_BOND_NOT_RECEIVED(); error L1_TOO_MANY_BLOCKS(); error L1_UNEXPECTED_PARENT(); /// @dev Proposes a Taiko L2 block. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _resolver Address resolver interface. /// @param _data Encoded data bytes containing the block params. /// @param _txList Transaction list bytes (if not blob). /// @return meta_ The constructed block's metadata. function proposeBlock( TaikoData.State storage _state, TaikoData.Config memory _config, IAddressResolver _resolver, bytes calldata _data, bytes calldata _txList ) internal returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_) { Local memory local; local.params = abi.decode(_data, (TaikoData.BlockParams)); if (local.params.coinbase == address(0)) { local.params.coinbase = msg.sender; } // Taiko, as a Based Rollup, enables permissionless block proposals. local.b = _state.slotB; // It's essential to ensure that the ring buffer for proposed blocks // still has space for at least one more block. if (local.b.numBlocks >= local.b.lastVerifiedBlockId + _config.blockMaxProposals + 1) { revert L1_TOO_MANY_BLOCKS(); } local.parentMetaHash = _state.blocks[(local.b.numBlocks - 1) % _config.blockRingBufferSize].metaHash; // assert(parentMetaHash != 0); // Check if parent block has the right meta hash. This is to allow the proposer to make sure // the block builds on the expected latest chain state. if (local.params.parentMetaHash != 0 && local.parentMetaHash != local.params.parentMetaHash) { revert L1_UNEXPECTED_PARENT(); } // Initialize metadata to compute a metaHash, which forms a part of // the block data to be stored on-chain for future integrity checks. // If we choose to persist all data fields in the metadata, it will // require additional storage slots. unchecked { meta_ = TaikoData.BlockMetadata({ l1Hash: blockhash(block.number - 1), difficulty: 0, // to be initialized below blobHash: 0, // to be initialized below extraData: local.params.extraData, depositsHash: _EMPTY_ETH_DEPOSIT_HASH, coinbase: local.params.coinbase, id: local.b.numBlocks, gasLimit: _config.blockMaxGasLimit, timestamp: uint64(block.timestamp), l1Height: uint64(block.number - 1), minTier: 0, // to be initialized below blobUsed: _txList.length == 0, parentMetaHash: local.parentMetaHash, sender: msg.sender }); } // Update certain meta fields if (meta_.blobUsed) { if (!LibNetwork.isDencunSupported(block.chainid)) revert L1_BLOB_NOT_AVAILABLE(); // Always use the first blob in this transaction. If the // proposeBlock functions are called more than once in the same // L1 transaction, these multiple L2 blocks will share the same // blob. meta_.blobHash = blobhash(0); if (meta_.blobHash == 0) revert L1_BLOB_NOT_FOUND(); } else { meta_.blobHash = keccak256(_txList); // This function must be called as the outmost transaction (not an internal one) for // the node to extract the calldata easily. // We cannot rely on `msg.sender != tx.origin` for EOA check, as it will break after EIP // 7645: Alias ORIGIN to SENDER if ( _config.checkEOAForCalldataDA && ECDSA.recover(meta_.blobHash, local.params.signature) != msg.sender ) { revert L1_INVALID_SIG(); } emit CalldataTxList(meta_.id, _txList); } // Following the Merge, the L1 mixHash incorporates the // prevrandao value from the beacon chain. Given the possibility // of multiple Taiko blocks being proposed within a single // Ethereum block, we choose to introduce a salt to this random // number as the L2 mixHash. meta_.difficulty = keccak256(abi.encodePacked(block.prevrandao, local.b.numBlocks, block.number)); { ITierRouter tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false)); ITierProvider tierProvider = ITierProvider(tierRouter.getProvider(local.b.numBlocks)); // Use the difficulty as a random number meta_.minTier = tierProvider.getMinTier(meta_.sender, uint256(meta_.difficulty)); } // Create the block that will be stored onchain TaikoData.Block memory blk = TaikoData.Block({ metaHash: LibUtils.hashMetadata(meta_), // Safeguard the liveness bond to ensure its preservation, // particularly in scenarios where it might be altered after the // block's proposal but before it has been proven or verified. assignedProver: address(0), livenessBond: _config.livenessBond, blockId: local.b.numBlocks, proposedAt: meta_.timestamp, proposedIn: uint64(block.number), // For a new block, the next transition ID is always 1, not 0. nextTransitionId: 1, // For unverified block, its verifiedTransitionId is always 0. verifiedTransitionId: 0 }); // Store the block in the ring buffer _state.blocks[local.b.numBlocks % _config.blockRingBufferSize] = blk; // Increment the counter (cursor) by 1. unchecked { ++_state.slotB.numBlocks; } LibBonds.debitBond(_state, _resolver, msg.sender, _config.livenessBond); // Bribe the block builder. Unlock 1559-tips, this tip is only made // if this transaction succeeds. if (msg.value != 0 && block.coinbase != address(0)) { address(block.coinbase).sendEtherAndVerify(msg.value); } deposits_ = new TaikoData.EthDeposit[](0); emit BlockProposed({ blockId: meta_.id, assignedProver: msg.sender, livenessBond: _config.livenessBond, meta: meta_, depositsProcessed: deposits_ }); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../../verifiers/IVerifier.sol"; import "./LibBonds.sol"; import "./LibUtils.sol"; /// @title LibProving /// @notice A library for handling block contestation and proving in the Taiko /// protocol. /// @custom:security-contact [email protected] library LibProving { using LibMath for uint256; // A struct to get around stack too deep issue and to cache state variables for multiple reads. struct Local { TaikoData.SlotB b; ITierProvider.Tier tier; ITierProvider.Tier minTier; bytes32 metaHash; address assignedProver; bytes32 stateRoot; uint96 livenessBond; uint64 slot; uint64 blockId; uint32 tid; bool lastUnpausedAt; bool isTopTier; bool inProvingWindow; bool sameTransition; } /// @notice Emitted when a transition is proved. /// @param blockId The block ID. /// @param tran The transition data. /// @param prover The prover's address. /// @param validityBond The validity bond amount. /// @param tier The tier of the proof. event TransitionProved( uint256 indexed blockId, TaikoData.Transition tran, address prover, uint96 validityBond, uint16 tier ); /// @notice Emitted when a transition is contested. /// @param blockId The block ID. /// @param tran The transition data. /// @param contester The contester's address. /// @param contestBond The contest bond amount. /// @param tier The tier of the proof. event TransitionContested( uint256 indexed blockId, TaikoData.Transition tran, address contester, uint96 contestBond, uint16 tier ); /// @notice Emitted when proving is paused or unpaused. /// @param paused The pause status. event ProvingPaused(bool paused); error L1_ALREADY_CONTESTED(); error L1_ALREADY_PROVED(); error L1_CANNOT_CONTEST(); error L1_INVALID_PAUSE_STATUS(); error L1_INVALID_TIER(); error L1_INVALID_TRANSITION(); error L1_NOT_ASSIGNED_PROVER(); error L1_PROVING_PAUSED(); /// @notice Pauses or unpauses the proving process. /// @param _state Current TaikoData.State. /// @param _pause The pause status. function pauseProving(TaikoData.State storage _state, bool _pause) internal { if (_state.slotB.provingPaused == _pause) revert L1_INVALID_PAUSE_STATUS(); _state.slotB.provingPaused = _pause; if (!_pause) { _state.slotB.lastUnpausedAt = uint64(block.timestamp); } emit ProvingPaused(_pause); } /// @dev Proves or contests a block transition. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _resolver Address resolver interface. /// @param _blockId The index of the block to prove. This is also used to /// select the right implementation version. /// @param _input An abi-encoded (TaikoData.BlockMetadata, TaikoData.Transition, /// TaikoData.TierProof) tuple. function proveBlock( TaikoData.State storage _state, TaikoData.Config memory _config, IAddressResolver _resolver, uint64 _blockId, bytes calldata _input ) internal { ( TaikoData.BlockMetadata memory meta, TaikoData.Transition memory tran, TaikoData.TierProof memory proof ) = abi.decode(_input, (TaikoData.BlockMetadata, TaikoData.Transition, TaikoData.TierProof)); if (_blockId != meta.id) revert LibUtils.L1_INVALID_BLOCK_ID(); // Make sure parentHash is not zero // To contest an existing transition, simply use any non-zero value as // the blockHash and stateRoot. if (tran.parentHash == 0 || tran.blockHash == 0 || tran.stateRoot == 0) { revert L1_INVALID_TRANSITION(); } Local memory local; local.b = _state.slotB; // Check that the block has been proposed but has not yet been verified. if (meta.id <= local.b.lastVerifiedBlockId || meta.id >= local.b.numBlocks) { revert LibUtils.L1_INVALID_BLOCK_ID(); } local.slot = meta.id % _config.blockRingBufferSize; TaikoData.Block storage blk = _state.blocks[local.slot]; local.blockId = blk.blockId; if (LibUtils.shouldSyncStateRoot(_config.stateRootSyncInternal, local.blockId)) { local.stateRoot = tran.stateRoot; } local.assignedProver = blk.assignedProver; if (local.assignedProver == address(0)) { local.assignedProver = meta.sender; } local.livenessBond = blk.livenessBond; local.metaHash = blk.metaHash; // Check the integrity of the block data. It's worth noting that in // theory, this check may be skipped, but it's included for added // caution. if (local.blockId != meta.id || local.metaHash != LibUtils.hashMetadata(meta)) { revert LibUtils.L1_BLOCK_MISMATCH(); } // Each transition is uniquely identified by the parentHash, with the // blockHash and stateRoot open for later updates as higher-tier proofs // become available. In cases where a transition with the specified // parentHash does not exist, the transition ID (tid) will be set to 0. TaikoData.TransitionState memory ts; (local.tid, ts) = _fetchOrCreateTransition(_state, blk, tran, local); // The new proof must meet or exceed the minimum tier required by the // block or the previous proof; it cannot be on a lower tier. if (proof.tier == 0 || proof.tier < meta.minTier || proof.tier < ts.tier) { revert L1_INVALID_TIER(); } // Retrieve the tier configurations. If the tier is not supported, the // subsequent action will result in a revert. { ITierRouter tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false)); ITierProvider tierProvider = ITierProvider(tierRouter.getProvider(local.blockId)); local.tier = tierProvider.getTier(proof.tier); local.minTier = tierProvider.getTier(meta.minTier); } local.inProvingWindow = !LibUtils.isPostDeadline({ _tsTimestamp: ts.timestamp, _lastUnpausedAt: local.b.lastUnpausedAt, _windowMinutes: local.minTier.provingWindow }); // Checks if only the assigned prover is permissioned to prove the block. // The assigned prover is granted exclusive permission to prove only the first // transition. if ( local.tier.contestBond != 0 && ts.contester == address(0) && local.tid == 1 && ts.tier == 0 && local.inProvingWindow ) { if (msg.sender != local.assignedProver) revert L1_NOT_ASSIGNED_PROVER(); } // We must verify the proof, and any failure in proof verification will // result in a revert. // // It's crucial to emphasize that the proof can be assessed in two // potential modes: "proving mode" and "contesting mode." However, the // precise verification logic is defined within each tier's IVerifier // contract implementation. We simply specify to the verifier contract // which mode it should utilize - if the new tier is higher than the // previous tier, we employ the proving mode; otherwise, we employ the // contesting mode (the new tier cannot be lower than the previous tier, // this has been checked above). // // It's obvious that proof verification is entirely decoupled from // Taiko's core protocol. if (local.tier.verifierName != "") { address verifier = _resolver.resolve(local.tier.verifierName, false); bool isContesting = proof.tier == ts.tier && local.tier.contestBond != 0; IVerifier.Context memory ctx = IVerifier.Context({ metaHash: local.metaHash, blobHash: meta.blobHash, // Separate msgSender to allow the prover to be any address in the future. prover: msg.sender, msgSender: msg.sender, blockId: local.blockId, isContesting: isContesting, blobUsed: meta.blobUsed }); IVerifier(verifier).verifyProof(ctx, tran, proof); } local.isTopTier = local.tier.contestBond == 0; local.sameTransition = tran.blockHash == ts.blockHash && local.stateRoot == ts.stateRoot; if (proof.tier > ts.tier) { // Handles the case when an incoming tier is higher than the current transition's tier. // Reverts when the incoming proof tries to prove the same transition // (L1_ALREADY_PROVED). _overrideWithHigherProof(_state, _resolver, blk, ts, tran, proof, local); emit TransitionProved({ blockId: local.blockId, tran: tran, prover: msg.sender, validityBond: local.tier.validityBond, tier: proof.tier }); } else { // New transition and old transition on the same tier - and if this transaction tries to // prove the same, it reverts if (local.sameTransition) revert L1_ALREADY_PROVED(); if (local.isTopTier) { // The top tier prover re-proves. assert(local.tier.validityBond == 0); assert(ts.validityBond == 0 && ts.contester == address(0)); ts.prover = msg.sender; ts.blockHash = tran.blockHash; ts.stateRoot = local.stateRoot; emit TransitionProved({ blockId: local.blockId, tran: tran, prover: msg.sender, validityBond: 0, tier: proof.tier }); } else { // Contesting but not on the highest tier if (ts.contester != address(0)) revert L1_ALREADY_CONTESTED(); // Making it a non-sliding window, relative when ts.timestamp was registered (or to // lastUnpaused if that one is bigger) if ( LibUtils.isPostDeadline( ts.timestamp, local.b.lastUnpausedAt, local.tier.cooldownWindow ) ) { revert L1_CANNOT_CONTEST(); } // _checkIfContestable(/*_state,*/ tier.cooldownWindow, ts.timestamp); // Burn the contest bond from the prover. LibBonds.debitBond(_state, _resolver, msg.sender, local.tier.contestBond); // We retain the contest bond within the transition, just in // case this configuration is altered to a different value // before the contest is resolved. // // It's worth noting that the previous value of ts.contestBond // doesn't have any significance. ts.contestBond = local.tier.contestBond; ts.contester = msg.sender; emit TransitionContested({ blockId: local.blockId, tran: tran, contester: msg.sender, contestBond: local.tier.contestBond, tier: proof.tier }); } } ts.timestamp = uint64(block.timestamp); _state.transitions[local.slot][local.tid] = ts; } /// @dev Handle the transition initialization logic function _fetchOrCreateTransition( TaikoData.State storage _state, TaikoData.Block storage _blk, TaikoData.Transition memory _tran, Local memory _local ) private returns (uint32 tid_, TaikoData.TransitionState memory ts_) { tid_ = LibUtils.getTransitionId(_state, _blk, _local.slot, _tran.parentHash); if (tid_ == 0) { // In cases where a transition with the provided parentHash is not // found, we must essentially "create" one and set it to its initial // state. This initial state can be viewed as a special transition // on tier-0. // // Subsequently, we transform this tier-0 transition into a // non-zero-tier transition with a proof. This approach ensures that // the same logic is applicable for both 0-to-non-zero transition // updates and non-zero-to-non-zero transition updates. unchecked { // Unchecked is safe: Not realistic 2**32 different fork choice // per block will be proven and none of them is valid tid_ = _blk.nextTransitionId++; } // Keep in mind that state.transitions are also reusable storage // slots, so it's necessary to reinitialize all transition fields // below. ts_.timestamp = _blk.proposedAt; if (tid_ == 1) { // This approach serves as a cost-saving technique for the // majority of blocks, where the first transition is expected to // be the correct one. Writing to `transitions` is more economical // since it resides in the ring buffer, whereas writing to // `transitionIds` is not as cost-effective. ts_.key = _tran.parentHash; // In the case of this first transition, the block's assigned // prover has the privilege to re-prove it, but only when the // assigned prover matches the previous prover. To ensure this, // we establish the transition's prover as the block's assigned // prover. Consequently, when we carry out a 0-to-non-zero // transition update, the previous prover will consistently be // the block's assigned prover. // // While alternative implementations are possible, introducing // such changes would require additional if-else logic. ts_.prover = _local.assignedProver; } else { // Furthermore, we index the transition for future retrieval. // It's worth emphasizing that this mapping for indexing is not // reusable. However, given that the majority of blocks will // only possess one transition — the correct one — we don't need // to be concerned about the cost in this case. // There is no need to initialize ts.key here because it's only used when tid == 1 _state.transitionIds[_local.blockId][_tran.parentHash] = tid_; } } else { // A transition with the provided parentHash has been located. ts_ = _state.transitions[_local.slot][tid_]; } } /// @dev Handles what happens when either the first transition is being proven or there is a /// higher tier proof incoming /// /// Assume Alice is the initial prover, Bob is the contester, and Cindy is the subsequent /// prover. The validity bond `V` is set at 100, and the contestation bond `C` at 500. If Bob /// successfully contests, he receives a reward of 65.625, calculated as 3/4 of 7/8 of 100. Cindy /// receives 21.875, which is 1/4 of 7/8 of 100, while the protocol retains 12.5 as friction. /// Bob's Return on Investment (ROI) is 13.125%, calculated from 65.625 divided by 500. // To establish the expected ROI `r` for valid contestations, where the contestation bond `C` to // validity bond `V` ratio is `C/V = 21/(32*r)`, and if `r` set at 10%, the C/V ratio will be // 6.5625. function _overrideWithHigherProof( TaikoData.State storage _state, IAddressResolver _resolver, TaikoData.Block storage _blk, TaikoData.TransitionState memory _ts, TaikoData.Transition memory _tran, TaikoData.TierProof memory _proof, Local memory _local ) private { // Higher tier proof overwriting lower tier proof uint256 reward; // reward to the new (current) prover if (_ts.contester != address(0)) { if (_local.sameTransition) { // The contested transition is proven to be valid, contester loses the game reward = _rewardAfterFriction(_ts.contestBond); // We return the validity bond back, but the original prover doesn't get any reward. LibBonds.creditBond(_state, _ts.prover, _ts.validityBond); } else { // The contested transition is proven to be invalid, contester wins the game. // Contester gets 3/4 of reward, the new prover gets 1/4. reward = _rewardAfterFriction(_ts.validityBond) >> 2; LibBonds.creditBond(_state, _ts.contester, _ts.contestBond + reward * 3); } } else { if (_local.sameTransition) revert L1_ALREADY_PROVED(); // The code below will be executed if // - 1) the transition is proved for the fist time, or // - 2) the transition is contested. reward = _rewardAfterFriction(_ts.validityBond); if (_local.livenessBond != 0) { // After the first proof, the block's liveness bond will always be reset to 0. // This means liveness bond will be handled only once for any given block. _blk.livenessBond = 0; if (_returnLivenessBond(_local, _proof.data)) { if (_local.assignedProver == msg.sender) { reward += _local.livenessBond; } else { LibBonds.creditBond(_state, _local.assignedProver, _local.livenessBond); } } } } unchecked { if (reward > _local.tier.validityBond) { LibBonds.creditBond(_state, msg.sender, reward - _local.tier.validityBond); } else if (reward < _local.tier.validityBond) { LibBonds.debitBond(_state, _resolver, msg.sender, _local.tier.validityBond - reward); } } _ts.validityBond = _local.tier.validityBond; _ts.contester = address(0); _ts.prover = msg.sender; _ts.tier = _proof.tier; if (!_local.sameTransition) { _ts.blockHash = _tran.blockHash; _ts.stateRoot = _local.stateRoot; } } /// @dev Returns the reward after applying 12.5% friction. function _rewardAfterFriction(uint256 _amount) private pure returns (uint256) { return _amount == 0 ? 0 : (_amount * 7) >> 3; } /// @dev Returns if the liveness bond shall be returned. function _returnLivenessBond( Local memory _local, bytes memory _proofData ) private pure returns (bool) { return _local.inProvingWindow && _local.tid == 1 || _local.isTopTier && _proofData.length == 32 && bytes32(_proofData) == LibStrings.H_RETURN_LIVENESS_BOND; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../../signal/ISignalService.sol"; import "./LibBonds.sol"; import "./LibUtils.sol"; /// @title LibVerifying /// @notice A library for handling block verification in the Taiko protocol. /// @custom:security-contact [email protected] library LibVerifying { using LibMath for uint256; struct Local { TaikoData.SlotB b; uint64 blockId; uint64 slot; uint64 numBlocksVerified; uint32 tid; uint32 lastVerifiedTransitionId; uint16 tier; bytes32 blockHash; bytes32 syncStateRoot; uint64 syncBlockId; uint32 syncTransitionId; address prover; ITierRouter tierRouter; } error L1_BLOCK_MISMATCH(); error L1_INVALID_CONFIG(); error L1_TRANSITION_ID_ZERO(); error L1_TOO_LATE(); /// @dev Verifies up to N blocks. function verifyBlocks( TaikoData.State storage _state, TaikoData.Config memory _config, IAddressResolver _resolver, uint64 _maxBlocksToVerify ) internal { if (_maxBlocksToVerify == 0) { return; } Local memory local; local.b = _state.slotB; local.blockId = local.b.lastVerifiedBlockId; local.slot = local.blockId % _config.blockRingBufferSize; TaikoData.Block storage blk = _state.blocks[local.slot]; if (blk.blockId != local.blockId) revert L1_BLOCK_MISMATCH(); local.lastVerifiedTransitionId = blk.verifiedTransitionId; local.tid = local.lastVerifiedTransitionId; // The following scenario should never occur but is included as a // precaution. if (local.tid == 0) revert L1_TRANSITION_ID_ZERO(); // The `blockHash` variable represents the most recently trusted // blockHash on L2. local.blockHash = _state.transitions[local.slot][local.tid].blockHash; // Unchecked is safe: // - assignment is within ranges // - blockId and numBlocksVerified values incremented will still be OK in the // next 584K years if we verifying one block per every second unchecked { ++local.blockId; while ( local.blockId < local.b.numBlocks && local.numBlocksVerified < _maxBlocksToVerify ) { local.slot = local.blockId % _config.blockRingBufferSize; blk = _state.blocks[local.slot]; if (blk.blockId != local.blockId) revert L1_BLOCK_MISMATCH(); local.tid = LibUtils.getTransitionId(_state, blk, local.slot, local.blockHash); // When `tid` is 0, it indicates that there is no proven // transition with its parentHash equal to the blockHash of the // most recently verified block. if (local.tid == 0) break; // A transition with the correct `parentHash` has been located. TaikoData.TransitionState storage ts = _state.transitions[local.slot][local.tid]; // It's not possible to verify this block if either the // transition is contested and awaiting higher-tier proof or if // the transition is still within its cooldown period. local.tier = ts.tier; if (ts.contester != address(0)) { break; } else { if (local.tierRouter == ITierRouter(address(0))) { local.tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false)); } uint24 cooldown = ITierProvider(local.tierRouter.getProvider(local.blockId)) .getTier(local.tier).cooldownWindow; if (!LibUtils.isPostDeadline(ts.timestamp, local.b.lastUnpausedAt, cooldown)) { // If cooldownWindow is 0, the block can theoretically // be proved and verified within the same L1 block. break; } } // Update variables local.lastVerifiedTransitionId = local.tid; local.blockHash = ts.blockHash; local.prover = ts.prover; LibBonds.creditBond(_state, local.prover, ts.validityBond); // Note: We exclusively address the bonds linked to the // transition used for verification. While there may exist // other transitions for this block, we disregard them entirely. // The bonds for these other transitions are burned (more precisely held in custody) // either when the transitions are generated or proven. In such cases, both the // provers and contesters of those transitions forfeit their bonds. emit LibUtils.BlockVerified({ blockId: local.blockId, prover: local.prover, blockHash: local.blockHash, stateRoot: 0, // DEPRECATED and is always zero. tier: local.tier }); if (LibUtils.shouldSyncStateRoot(_config.stateRootSyncInternal, local.blockId)) { bytes32 stateRoot = ts.stateRoot; if (stateRoot != 0) { local.syncStateRoot = stateRoot; local.syncBlockId = local.blockId; local.syncTransitionId = local.tid; } } ++local.blockId; ++local.numBlocksVerified; } if (local.numBlocksVerified != 0) { uint64 lastVerifiedBlockId = local.b.lastVerifiedBlockId + local.numBlocksVerified; local.slot = lastVerifiedBlockId % _config.blockRingBufferSize; _state.slotB.lastVerifiedBlockId = lastVerifiedBlockId; _state.blocks[local.slot].verifiedTransitionId = local.lastVerifiedTransitionId; if (local.syncStateRoot != 0) { _state.slotA.lastSyncedBlockId = local.syncBlockId; _state.slotA.lastSynecdAt = uint64(block.timestamp); // We write the synced block's verifiedTransitionId to storage if (local.syncBlockId != lastVerifiedBlockId) { local.slot = local.syncBlockId % _config.blockRingBufferSize; _state.blocks[local.slot].verifiedTransitionId = local.syncTransitionId; } // Ask signal service to write cross chain signal ISignalService(_resolver.resolve(LibStrings.B_SIGNAL_SERVICE, false)) .syncChainData( _config.chainId, LibStrings.H_STATE_ROOT, local.syncBlockId, local.syncStateRoot ); } } } } function getVerifiedBlockProver( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId ) internal view returns (address) { (TaikoData.Block storage blk,) = LibUtils.getBlock(_state, _config, _blockId); uint32 tid = blk.verifiedTransitionId; if (tid == 0) return address(0); return LibUtils.getTransition(_state, _config, _blockId, tid).prover; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./TaikoData.sol"; /// @title ITaikoL1 /// @custom:security-contact [email protected] interface ITaikoL1 { /// @notice Proposes a Taiko L2 block. /// @param _params Block parameters, currently an encoded BlockParams object. /// @param _txList txList data if calldata is used for DA. /// @return meta_ The metadata of the proposed L2 block. /// @return deposits_ The Ether deposits processed. function proposeBlock( bytes calldata _params, bytes calldata _txList ) external payable returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_); /// @notice Proves or contests a block transition. /// @param _blockId The index of the block to prove. This is also used to /// select the right implementation version. /// @param _input An abi-encoded (TaikoData.BlockMetadata, TaikoData.Transition, /// TaikoData.TierProof) tuple. function proveBlock(uint64 _blockId, bytes calldata _input) external; /// @notice Verifies up to a certain number of blocks. /// @param _maxBlocksToVerify Max number of blocks to verify. function verifyBlocks(uint64 _maxBlocksToVerify) external; /// @notice Pause block proving. /// @param _pause True if paused. function pauseProving(bool _pause) external; /// @notice Deposits Taiko token to be used as bonds. /// @param _amount The amount of Taiko token to deposit. function depositBond(uint256 _amount) external; /// @notice Withdraws Taiko token. /// @param _amount The amount of Taiko token to withdraw. function withdrawBond(uint256 _amount) external; /// @notice Gets the prover that actually proved a verified block. /// @param _blockId The index of the block. /// @return The prover's address. If the block is not verified yet, address(0) will be returned. function getVerifiedBlockProver(uint64 _blockId) external view returns (address); /// @notice Gets the configuration of the TaikoL1 contract. /// @return Config struct containing configuration parameters. function getConfig() external pure returns (TaikoData.Config memory); }
// 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; }
// 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; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./IAddressManager.sol"; import "./IAddressResolver.sol"; /// @title AddressResolver /// @notice See the documentation in {IAddressResolver}. /// @custom:security-contact [email protected] abstract contract AddressResolver is IAddressResolver, Initializable { /// @notice Address of the AddressManager. address public addressManager; uint256[49] private __gap; error RESOLVER_DENIED(); error RESOLVER_INVALID_MANAGER(); error RESOLVER_UNEXPECTED_CHAINID(); error RESOLVER_ZERO_ADDR(uint64 chainId, bytes32 name); /// @dev Modifier that ensures the caller is the resolved address of a given /// name. /// @param _name The name to check against. modifier onlyFromNamed(bytes32 _name) { if (msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); _; } /// @dev Modifier that ensures the caller is a resolved address to either _name1 or _name2 /// name. /// @param _name1 The first name to check against. /// @param _name2 The second name to check against. modifier onlyFromNamedEither(bytes32 _name1, bytes32 _name2) { if (msg.sender != resolve(_name1, true) && msg.sender != resolve(_name2, true)) { revert RESOLVER_DENIED(); } _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @inheritdoc IAddressResolver function resolve( bytes32 _name, bool _allowZeroAddress ) public view virtual returns (address payable) { return _resolve(uint64(block.chainid), _name, _allowZeroAddress); } /// @inheritdoc IAddressResolver function resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) public view virtual returns (address payable) { return _resolve(_chainId, _name, _allowZeroAddress); } /// @dev Initialization method for setting up AddressManager reference. /// @param _addressManager Address of the AddressManager. function __AddressResolver_init(address _addressManager) internal virtual onlyInitializing { if (block.chainid > type(uint64).max) { revert RESOLVER_UNEXPECTED_CHAINID(); } addressManager = _addressManager; } /// @dev Helper method to resolve name-to-address. /// @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 addr_ Address associated with the given name on the specified /// chain. function _resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) private view returns (address payable addr_) { address _addressManager = addressManager; if (_addressManager == address(0)) revert RESOLVER_INVALID_MANAGER(); addr_ = payable(IAddressManager(_addressManager).getAddress(_chainId, _name)); if (!_allowZeroAddress && addr_ == address(0)) { revert RESOLVER_ZERO_ADDR(_chainId, _name); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibNetwork library LibNetwork { uint256 internal constant MAINNET = 1; uint256 internal constant ROPSTEN = 2; uint256 internal constant RINKEBY = 4; uint256 internal constant GOERLI = 5; uint256 internal constant KOVAN = 42; uint256 internal constant HOLESKY = 17_000; uint256 internal constant SEPOLIA = 11_155_111; uint64 internal constant TAIKO_MAINNET = 167_000; uint64 internal constant TAIKO_HEKLA = 167_009; /// @dev Checks if the chain ID represents an Ethereum testnet. /// @param _chainId The chain ID. /// @return true if the chain ID represents an Ethereum testnet, false otherwise. function isEthereumTestnet(uint256 _chainId) internal pure returns (bool) { return _chainId == LibNetwork.ROPSTEN || _chainId == LibNetwork.RINKEBY || _chainId == LibNetwork.GOERLI || _chainId == LibNetwork.KOVAN || _chainId == LibNetwork.HOLESKY || _chainId == LibNetwork.SEPOLIA; } /// @dev Checks if the chain ID represents an Ethereum testnet or the Etheruem mainnet. /// @param _chainId The chain ID. /// @return true if the chain ID represents an Ethereum testnet or the Etheruem mainnet, false /// otherwise. function isEthereumMainnetOrTestnet(uint256 _chainId) internal pure returns (bool) { return _chainId == LibNetwork.MAINNET || isEthereumTestnet(_chainId); } /// @dev Checks if the chain ID represents the Taiko L2 mainnet. /// @param _chainId The chain ID. /// @return true if the chain ID represents the Taiko L2 mainnet. function isTaikoMainnet(uint256 _chainId) internal pure returns (bool) { return _chainId == TAIKO_MAINNET; } /// @dev Checks if the chain ID represents an internal Taiko devnet's base layer. /// @param _chainId The chain ID. /// @return true if the chain ID represents an internal Taiko devnet's base layer, false /// otherwise. function isTaikoDevnet(uint256 _chainId) internal pure returns (bool) { return _chainId >= 32_300 && _chainId <= 32_400; } /// @dev Checks if the chain supports Dencun hardfork. Note that this check doesn't need to be /// exhaustive. /// @param _chainId The chain ID. /// @return true if the chain supports Dencun hardfork, false otherwise. function isDencunSupported(uint256 _chainId) internal pure returns (bool) { return _chainId == LibNetwork.MAINNET || _chainId == LibNetwork.HOLESKY || _chainId == LibNetwork.SEPOLIA || isTaikoDevnet(_chainId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "@openzeppelin/contracts/interfaces/IERC1271.sol"; /// @title LibAddress /// @dev Provides utilities for address-related operations. /// @custom:security-contact [email protected] library LibAddress { error ETH_TRANSFER_FAILED(); /// @dev Sends Ether to the specified address. This method will not revert even if sending ether /// fails. /// This function is inspired by /// https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol /// @param _to The recipient address. /// @param _amount The amount of Ether to send in wei. /// @param _gasLimit The max amount gas to pay for this transaction. /// @return success_ true if the call is successful, false otherwise. function sendEther( address _to, uint256 _amount, uint256 _gasLimit, bytes memory _calldata ) internal returns (bool success_) { // Check for zero-address transactions if (_to == address(0)) revert ETH_TRANSFER_FAILED(); // dispatch message to recipient // by assembly calling "handle" function // we call via assembly to avoid memcopying a very large returndata // returned by a malicious contract assembly { success_ := call( _gasLimit, // gas _to, // recipient _amount, // ether value add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc 0 // outlen ) } } /// @dev Sends Ether to the specified address. This method will revert if sending ether fails. /// @param _to The recipient address. /// @param _amount The amount of Ether to send in wei. /// @param _gasLimit The max amount gas to pay for this transaction. function sendEtherAndVerify(address _to, uint256 _amount, uint256 _gasLimit) internal { if (_amount == 0) return; if (!sendEther(_to, _amount, _gasLimit, "")) { revert ETH_TRANSFER_FAILED(); } } /// @dev Sends Ether to the specified address. This method will revert if sending ether fails. /// @param _to The recipient address. /// @param _amount The amount of Ether to send in wei. function sendEtherAndVerify(address _to, uint256 _amount) internal { sendEtherAndVerify(_to, _amount, gasleft()); } function supportsInterface( address _addr, bytes4 _interfaceId ) internal view returns (bool result_) { if (!Address.isContract(_addr)) return false; try IERC165(_addr).supportsInterface(_interfaceId) returns (bool _result) { result_ = _result; } catch { } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../../common/IAddressResolver.sol"; import "../../common/LibStrings.sol"; import "../TaikoData.sol"; /// @title LibBonds /// @notice A library that offers helper functions to handle bonds. /// @custom:security-contact [email protected] library LibBonds { /// @dev Emitted when token is credited back to a user's bond balance. event BondCredited(address indexed user, uint256 amount); /// @dev Emitted when token is debited from a user's bond balance. event BondDebited(address indexed user, uint256 amount); /// @dev Deposits Taiko token to be used as bonds. /// @param _state Current TaikoData.State. /// @param _resolver Address resolver interface. /// @param _amount The amount of token to deposit. function depositBond( TaikoData.State storage _state, IAddressResolver _resolver, uint256 _amount ) internal { _state.bondBalance[msg.sender] += _amount; _tko(_resolver).transferFrom(msg.sender, address(this), _amount); } /// @dev Withdraws Taiko token. /// @param _state Current TaikoData.State. /// @param _resolver Address resolver interface. /// @param _amount The amount of token to withdraw. function withdrawBond( TaikoData.State storage _state, IAddressResolver _resolver, uint256 _amount ) internal { _state.bondBalance[msg.sender] -= _amount; _tko(_resolver).transfer(msg.sender, _amount); } /// @dev Debits Taiko tokens as bonds. /// @param _state Current TaikoData.State. /// @param _resolver Address resolver interface. /// @param _user The user address to debit. /// @param _amount The amount of token to debit. function debitBond( TaikoData.State storage _state, IAddressResolver _resolver, address _user, uint256 _amount ) internal { uint256 balance = _state.bondBalance[_user]; if (balance >= _amount) { unchecked { _state.bondBalance[_user] = balance - _amount; } emit BondDebited(_user, _amount); } else { _tko(_resolver).transferFrom(_user, address(this), _amount); } } /// @dev Credits Taiko tokens to user's bond balance. /// @param _state Current TaikoData.State. /// @param _user The user address to credit. /// @param _amount The amount of token to credit. function creditBond(TaikoData.State storage _state, address _user, uint256 _amount) internal { _state.bondBalance[_user] += _amount; emit BondCredited(_user, _amount); } /// @dev Gets a user's current Taiko token bond balance. /// @param _state Current TaikoData.State. /// @param _user The user address to credit. /// @return The current token balance. function bondBalanceOf( TaikoData.State storage _state, address _user ) internal view returns (uint256) { return _state.bondBalance[_user]; } function _tko(IAddressResolver _resolver) private view returns (IERC20) { return IERC20(_resolver.resolve(LibStrings.B_TAIKO_TOKEN, false)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../../common/IAddressResolver.sol"; import "../../common/LibStrings.sol"; import "../../libs/LibMath.sol"; import "../tiers/ITierProvider.sol"; import "../tiers/ITierRouter.sol"; import "../TaikoData.sol"; /// @title LibUtils /// @notice A library that offers helper functions. /// @custom:security-contact [email protected] library LibUtils { using LibMath for uint256; /// @dev Emitted when a block is verified. /// @param blockId The ID of the verified block. /// @param prover The prover whose transition is used for verifying the /// block. /// @param blockHash The hash of the verified block. /// @param stateRoot Deprecated and is always zero. /// @param tier The tier ID of the proof. event BlockVerified( uint256 indexed blockId, address indexed prover, bytes32 blockHash, bytes32 stateRoot, uint16 tier ); error L1_BLOCK_MISMATCH(); error L1_INVALID_BLOCK_ID(); error L1_INVALID_GENESIS_HASH(); error L1_TRANSITION_NOT_FOUND(); error L1_UNEXPECTED_TRANSITION_ID(); /// @notice Initializes the Taiko protocol state. /// @param _state The state to initialize. /// @param _genesisBlockHash The block hash of the genesis block. function init(TaikoData.State storage _state, bytes32 _genesisBlockHash) internal { if (_genesisBlockHash == 0) revert L1_INVALID_GENESIS_HASH(); // Init state _state.slotA.genesisHeight = uint64(block.number); _state.slotA.genesisTimestamp = uint64(block.timestamp); _state.slotB.numBlocks = 1; // Init the genesis block TaikoData.Block storage blk = _state.blocks[0]; blk.nextTransitionId = 2; blk.proposedAt = uint64(block.timestamp); blk.verifiedTransitionId = 1; blk.metaHash = bytes32(uint256(1)); // Give the genesis metahash a non-zero value. // Init the first state transition TaikoData.TransitionState storage ts = _state.transitions[0][1]; ts.blockHash = _genesisBlockHash; ts.prover = address(0); ts.timestamp = uint64(block.timestamp); emit BlockVerified({ blockId: 0, prover: address(0), blockHash: _genesisBlockHash, stateRoot: 0, tier: 0 }); } /// @dev Retrieves a block based on its ID. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @return blk_ The block storage pointer. /// @return slot_ The slot value. function getBlock( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId ) internal view returns (TaikoData.Block storage blk_, uint64 slot_) { slot_ = _blockId % _config.blockRingBufferSize; blk_ = _state.blocks[slot_]; if (blk_.blockId != _blockId) revert L1_INVALID_BLOCK_ID(); } /// @dev Retrieves a block's block hash and state root. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @return blockHash_ The block's block hash. /// @return stateRoot_ The block's storage root. function getBlockInfo( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId ) internal view returns (bytes32 blockHash_, bytes32 stateRoot_) { (TaikoData.Block storage blk, uint64 slot) = getBlock(_state, _config, _blockId); if (blk.verifiedTransitionId != 0) { TaikoData.TransitionState storage transition = _state.transitions[slot][blk.verifiedTransitionId]; blockHash_ = transition.blockHash; stateRoot_ = transition.stateRoot; } } /// @notice This function will revert if the transition is not found. /// @dev Retrieves the transition with a given parentHash. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @param _tid The transition id. /// @return The state transition pointer. function getTransition( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId, uint32 _tid ) internal view returns (TaikoData.TransitionState storage) { (TaikoData.Block storage blk, uint64 slot) = getBlock(_state, _config, _blockId); if (_tid == 0 || _tid >= blk.nextTransitionId) revert L1_TRANSITION_NOT_FOUND(); return _state.transitions[slot][_tid]; } /// @notice This function will revert if the transition is not found. /// @dev Retrieves the transition with a given parentHash. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @param _parentHash Parent hash of the block. /// @return The state transition pointer. function getTransition( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId, bytes32 _parentHash ) internal view returns (TaikoData.TransitionState storage) { (TaikoData.Block storage blk, uint64 slot) = getBlock(_state, _config, _blockId); uint32 tid = getTransitionId(_state, blk, slot, _parentHash); if (tid == 0) revert L1_TRANSITION_NOT_FOUND(); return _state.transitions[slot][tid]; } /// @dev Retrieves the ID of the transition with a given parentHash. /// This function will return 0 if the transition is not found. function getTransitionId( TaikoData.State storage _state, TaikoData.Block storage _blk, uint64 _slot, bytes32 _parentHash ) internal view returns (uint32 tid_) { if (_state.transitions[_slot][1].key == _parentHash) { tid_ = 1; if (tid_ >= _blk.nextTransitionId) revert L1_UNEXPECTED_TRANSITION_ID(); } else { tid_ = _state.transitionIds[_blk.blockId][_parentHash]; if (tid_ != 0 && tid_ >= _blk.nextTransitionId) revert L1_UNEXPECTED_TRANSITION_ID(); } } function isPostDeadline( uint256 _tsTimestamp, uint256 _lastUnpausedAt, uint256 _windowMinutes ) internal view returns (bool) { unchecked { uint256 deadline = _tsTimestamp.max(_lastUnpausedAt) + _windowMinutes * 60; return block.timestamp >= deadline; } } function shouldVerifyBlocks( TaikoData.Config memory _config, uint64 _blockId, bool _isBlockProposed ) internal pure returns (bool) { if (_config.maxBlocksToVerify == 0) return false; // Consider each segment of 8 blocks, verification is attempted either on block 3 if it has // been // proved, or on block 7 if it has been proposed. Over time, the ratio of blocks to // verification attempts averages 4:1, meaning each verification attempt typically covers 4 // blocks. However, considering worst cases caused by blocks being proved out of order, some // verification attempts may verify few or no blocks. In such cases, additional // verifications are needed to catch up. Consequently, the `maxBlocksToVerify` parameter // should be set high enough, for example 16, to allow for efficient catch-up. // Now lets use `maxBlocksToVerify` as an input to calculate the size of each block // segment, instead of using 8 as a constant. uint256 segmentSize = _config.maxBlocksToVerify >> 1; if (segmentSize <= 1) return true; return _blockId % segmentSize == (_isBlockProposed ? 0 : segmentSize >> 1); } function shouldSyncStateRoot( uint256 _stateRootSyncInternal, uint256 _blockId ) internal pure returns (bool) { if (_stateRootSyncInternal <= 1) return true; unchecked { // We could use `_blockId % _stateRootSyncInternal == 0`, but this will break many unit // tests as in most of these tests, we test block#1, so by setting // config._stateRootSyncInternal = 2, we can keep the tests unchanged. return _blockId % _stateRootSyncInternal == _stateRootSyncInternal - 1; } } function hashMetadata(TaikoData.BlockMetadata memory _meta) internal pure returns (bytes32) { return keccak256(abi.encode(_meta)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../L1/TaikoData.sol"; /// @title IVerifier /// @notice Defines the function that handles proof verification. /// @custom:security-contact [email protected] interface IVerifier { struct Context { bytes32 metaHash; bytes32 blobHash; address prover; uint64 blockId; bool isContesting; bool blobUsed; address msgSender; } /// @notice Verifies a proof. /// @param _ctx The context of the proof verification. /// @param _tran The transition to verify. /// @param _proof The proof to verify. function verifyProof( Context calldata _ctx, TaikoData.Transition calldata _tran, TaikoData.TierProof calldata _proof ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title ISignalService /// @notice The SignalService contract serves as a secure cross-chain message /// passing system. It defines methods for sending and verifying signals with /// merkle proofs. The trust assumption is that the target chain has secure /// access to the merkle root (such as Taiko injects it in the anchor /// transaction). With this, verifying a signal is reduced to simply verifying /// a merkle proof. /// @custom:security-contact [email protected] interface ISignalService { enum CacheOption { CACHE_NOTHING, CACHE_SIGNAL_ROOT, CACHE_STATE_ROOT, CACHE_BOTH } struct HopProof { /// @notice This hop's destination chain ID. If there is a next hop, this ID is the next /// hop's source chain ID. uint64 chainId; /// @notice The ID of a source chain block whose state root has been synced to the hop's /// destination chain. /// Note that this block ID must be greater than or equal to the block ID where the signal /// was sent on the source chain. uint64 blockId; /// @notice The state root or signal root of the source chain at the above blockId. This /// value has been synced to the destination chain. /// @dev To get both the blockId and the rootHash, apps should subscribe to the /// ChainDataSynced event or query `topBlockId` first using the source chain's ID and /// LibStrings.H_STATE_ROOT to get the most recent block ID synced, then call /// `getSyncedChainData` to read the synchronized data. bytes32 rootHash; /// @notice Options to cache either the state roots or signal roots of middle-hops to the /// current chain. CacheOption cacheOption; /// @notice The signal service's account proof. If this value is empty, then `rootHash` will /// be used as the signal root, otherwise, `rootHash` will be used as the state root. bytes[] accountProof; /// @notice The signal service's storage proof. bytes[] storageProof; } /// @notice Emitted when a remote chain's state root or signal root is /// synced locally as a signal. /// @param chainId The remote chainId. /// @param blockId The chain data's corresponding blockId. /// @param kind A value to mark the data type. /// @param data The remote data. /// @param signal The signal for this chain data. event ChainDataSynced( uint64 indexed chainId, uint64 indexed blockId, bytes32 indexed kind, bytes32 data, bytes32 signal ); /// @notice Emitted when a signal is sent. /// @param app The address that initiated the signal. /// @param signal The signal (message) that was sent. /// @param slot The location in storage where this signal is stored. /// @param value The value of the signal. event SignalSent(address app, bytes32 signal, bytes32 slot, bytes32 value); /// @notice Emitted when an address is authorized or deauthorized. /// @param addr The address to be authorized or deauthorized. /// @param authorized True if authorized, false otherwise. event Authorized(address indexed addr, bool authorized); /// @notice Send a signal (message) by setting the storage slot to the same value as the signal /// itself. /// @param _signal The signal (message) to send. /// @return slot_ The location in storage where this signal is stored. function sendSignal(bytes32 _signal) external returns (bytes32 slot_); /// @notice Sync a data from a remote chain locally as a signal. The signal is calculated /// uniquely from chainId, kind, and data. /// @param _chainId The remote chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding blockId /// @param _chainData The remote data. /// @return signal_ The signal for this chain data. function syncChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) external returns (bytes32 signal_); /// @notice Verifies if a signal has been received on the target chain. /// @param _chainId The identifier for the source chain from which the /// signal originated. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) to send. /// @param _proof Merkle proof that the signal was persisted on the /// source chain. /// @return numCacheOps_ The number of newly cached items. function proveSignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external returns (uint256 numCacheOps_); /// @notice Verifies if a signal has been received on the target chain. /// This is the "readonly" version of proveSignalReceived. /// @param _chainId The identifier for the source chain from which the /// signal originated. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) to send. /// @param _proof Merkle proof that the signal was persisted on the /// source chain. function verifySignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external view; /// @notice Verifies if a particular signal has already been sent. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) that was sent. /// @return true if the signal has been sent, otherwise false. function isSignalSent(address _app, bytes32 _signal) external view returns (bool); /// @notice Checks if a chain data has been synced. /// @param _chainId The remote chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding blockId /// @param _chainData The remote data. /// @return true if the data has been synced, otherwise false. function isChainDataSynced( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) external view returns (bool); /// @notice Returns the given block's chain data. /// @param _chainId Identifier of the chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding block id. If this value is 0, use the top /// block id. /// @return blockId_ The actual block id. /// @return chainData_ The synced chain data. function getSyncedChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) external view returns (uint64 blockId_, bytes32 chainData_); /// @notice Returns the data to be used for caching slot generation. /// @param _chainId Identifier of the chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding block id. If this value is 0, use the top /// block id. /// @return signal_ The signal used for caching slot creation. function signalForChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) external pure returns (bytes32 signal_); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title TaikoData /// @notice This library defines various data structures used in the Taiko /// protocol. /// @custom:security-contact [email protected] library TaikoData { /// @dev Struct holding Taiko configuration parameters. See {TaikoConfig}. struct Config { // --------------------------------------------------------------------- // Group 1: General configs // --------------------------------------------------------------------- // The chain ID of the network where Taiko contracts are deployed. uint64 chainId; // --------------------------------------------------------------------- // Group 2: Block level configs // --------------------------------------------------------------------- // The maximum number of proposals allowed in a single block. uint64 blockMaxProposals; // Size of the block ring buffer, allowing extra space for proposals. uint64 blockRingBufferSize; // The maximum number of verifications allowed when a block is proposed // or proved. uint64 maxBlocksToVerify; // The maximum gas limit allowed for a block. uint32 blockMaxGasLimit; // --------------------------------------------------------------------- // Group 3: Proof related configs // --------------------------------------------------------------------- // The amount of Taiko token as a prover liveness bond uint96 livenessBond; // --------------------------------------------------------------------- // Group 4: Cross-chain sync // --------------------------------------------------------------------- // The number of L2 blocks between each L2-to-L1 state root sync. uint8 stateRootSyncInternal; bool checkEOAForCalldataDA; } /// @dev A proof and the tier of proof it belongs to struct TierProof { uint16 tier; bytes data; } /// @dev Hook and it's data (currently used only during proposeBlock) struct HookCall { address hook; bytes data; } /// @dev Represents proposeBlock's _data input parameter struct BlockParams { address assignedProver; // DEPRECATED, value ignored. address coinbase; bytes32 extraData; bytes32 parentMetaHash; HookCall[] hookCalls; // DEPRECATED, value ignored. bytes signature; } /// @dev Struct containing data only required for proving a block /// Note: On L2, `block.difficulty` is the pseudo name of /// `block.prevrandao`, which returns a random number provided by the layer /// 1 chain. struct BlockMetadata { bytes32 l1Hash; bytes32 difficulty; bytes32 blobHash; //or txListHash (if Blob not yet supported) bytes32 extraData; bytes32 depositsHash; address coinbase; // L2 coinbase, uint64 id; uint32 gasLimit; uint64 timestamp; uint64 l1Height; uint16 minTier; bool blobUsed; bytes32 parentMetaHash; address sender; // a.k.a proposer } /// @dev Struct representing transition to be proven. struct Transition { bytes32 parentHash; bytes32 blockHash; bytes32 stateRoot; bytes32 graffiti; // Arbitrary data that the prover can use for various purposes. } /// @dev Struct representing state transition data. /// 6 slots used. struct TransitionState { bytes32 key; // slot 1, only written/read for the 1st state transition. bytes32 blockHash; // slot 2 bytes32 stateRoot; // slot 3 address prover; // slot 4 uint96 validityBond; address contester; // slot 5 uint96 contestBond; uint64 timestamp; // slot 6 (90 bits) uint16 tier; uint8 __reserved1; } /// @dev Struct containing data required for verifying a block. /// 3 slots used. struct Block { bytes32 metaHash; // slot 1 address assignedProver; // slot 2 uint96 livenessBond; uint64 blockId; // slot 3 uint64 proposedAt; // timestamp uint64 proposedIn; // L1 block number, required/used by node/client. uint32 nextTransitionId; // The ID of the transaction that is used to verify this block. However, if // this block is not verified as the last block in a batch, verifiedTransitionId // will remain zero. uint32 verifiedTransitionId; } /// @dev Struct representing an Ethereum deposit. /// 2 slot used. Currently removed from protocol, but to be backwards compatible, the struct and /// return values stayed for now. struct EthDeposit { address recipient; uint96 amount; uint64 id; } /// @dev Forge is only able to run coverage in case the contracts by default /// capable of compiling without any optimization (neither optimizer runs, /// no compiling --via-ir flag). /// In order to resolve stack too deep without optimizations, we needed to /// introduce outsourcing vars into structs below. struct SlotA { uint64 genesisHeight; uint64 genesisTimestamp; uint64 lastSyncedBlockId; uint64 lastSynecdAt; // typo! } struct SlotB { uint64 numBlocks; uint64 lastVerifiedBlockId; bool provingPaused; uint8 __reservedB1; uint16 __reservedB2; uint32 __reservedB3; uint64 lastUnpausedAt; } /// @dev Struct holding the state variables for the {TaikoL1} contract. struct State { // Ring buffer for proposed blocks and a some recent verified blocks. mapping(uint64 blockId_mod_blockRingBufferSize => Block blk) blocks; // Indexing to transition ids (ring buffer not possible) mapping(uint64 blockId => mapping(bytes32 parentHash => uint32 transitionId)) transitionIds; // Ring buffer for transitions mapping( uint64 blockId_mod_blockRingBufferSize => mapping(uint32 transitionId => TransitionState ts) ) transitions; // Ring buffer for Ether deposits bytes32 __reserve1; SlotA slotA; // slot 5 SlotB slotB; // slot 6 mapping(address account => uint256 bond) bondBalance; uint256[43] __gap; } }
// 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); }
// 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); } } }
// 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; }
// 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; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title IAddressManager /// @notice Manages a mapping of (chainId, name) pairs to Ethereum addresses. /// @custom:security-contact [email protected] interface IAddressManager { /// @notice Gets the address mapped to a specific chainId-name pair. /// @dev Note that in production, this method shall be a pure function /// without any storage access. /// @param _chainId The chainId for which the address needs to be fetched. /// @param _name The name for which the address needs to be fetched. /// @return Address associated with the chainId-name pair. function getAddress(uint64 _chainId, bytes32 _name) external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title IAddressResolver /// @notice This contract acts as a bridge for name-to-address resolution. /// It delegates the resolution to the AddressManager. By separating the logic, /// we can maintain flexibility in address management without affecting the /// resolving process. /// @dev Note that the address manager should be changed using upgradability, there /// is no setAddressManager() function to guarantee atomicity across all /// contracts that are resolvers. /// @custom:security-contact [email protected] interface IAddressResolver { /// @notice Resolves a name to its address deployed on this chain. /// @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. function resolve( bytes32 _name, bool _allowZeroAddress ) external view returns (address payable); /// @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( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) external view returns (address payable); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// 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); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// 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); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibStrings /// @custom:security-contact [email protected] library LibStrings { bytes32 internal constant B_AUTOMATA_DCAP_ATTESTATION = bytes32("automata_dcap_attestation"); bytes32 internal constant B_BRIDGE = bytes32("bridge"); bytes32 internal constant B_BRIDGE_WATCHDOG = bytes32("bridge_watchdog"); bytes32 internal constant B_BRIDGED_ERC1155 = bytes32("bridged_erc1155"); bytes32 internal constant B_BRIDGED_ERC20 = bytes32("bridged_erc20"); bytes32 internal constant B_BRIDGED_ERC721 = bytes32("bridged_erc721"); bytes32 internal constant B_CHAIN_WATCHDOG = bytes32("chain_watchdog"); bytes32 internal constant B_ERC1155_VAULT = bytes32("erc1155_vault"); bytes32 internal constant B_ERC20_VAULT = bytes32("erc20_vault"); bytes32 internal constant B_ERC721_VAULT = bytes32("erc721_vault"); bytes32 internal constant B_PROVER_ASSIGNMENT = bytes32("PROVER_ASSIGNMENT"); bytes32 internal constant B_PROVER_SET = bytes32("prover_set"); bytes32 internal constant B_QUOTA_MANAGER = bytes32("quota_manager"); bytes32 internal constant B_SGX_WATCHDOG = bytes32("sgx_watchdog"); bytes32 internal constant B_SIGNAL_SERVICE = bytes32("signal_service"); bytes32 internal constant B_TAIKO = bytes32("taiko"); bytes32 internal constant B_TAIKO_TOKEN = bytes32("taiko_token"); bytes32 internal constant B_TIER_GUARDIAN = bytes32("tier_guardian"); bytes32 internal constant B_TIER_GUARDIAN_MINORITY = bytes32("tier_guardian_minority"); bytes32 internal constant B_TIER_ROUTER = bytes32("tier_router"); bytes32 internal constant B_TIER_SGX = bytes32("tier_sgx"); bytes32 internal constant B_TIER_SGX2 = bytes32("tier_sgx2"); bytes32 internal constant B_TIER_ZKVM_RISC0 = bytes32("tier_zkvm_risc0"); bytes32 internal constant B_TIER_SGX_ZKVM = bytes32("tier_sgx_zkvm"); bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer"); bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND"); bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT"); bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT"); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibMath /// @dev This library offers additional math functions for uint256. /// @custom:security-contact [email protected] library LibMath { /// @dev Returns the smaller of the two given values. /// @param _a The first number to compare. /// @param _b The second number to compare. /// @return The smaller of the two numbers. function min(uint256 _a, uint256 _b) internal pure returns (uint256) { return _a > _b ? _b : _a; } /// @dev Returns the larger of the two given values. /// @param _a The first number to compare. /// @param _b The second number to compare. /// @return The larger of the two numbers. function max(uint256 _a, uint256 _b) internal pure returns (uint256) { return _a > _b ? _a : _b; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title ITierProvider /// @notice Defines interface to return tier configuration. /// @custom:security-contact [email protected] interface ITierProvider { struct Tier { bytes32 verifierName; uint96 validityBond; uint96 contestBond; uint24 cooldownWindow; // in minutes uint16 provingWindow; // in minutes uint8 maxBlocksToVerifyPerProof; // DEPRECATED } error TIER_NOT_FOUND(); /// @dev Retrieves the configuration for a specified tier. /// @param tierId ID of the tier. /// @return Tier struct containing the tier's parameters. function getTier(uint16 tierId) external view returns (Tier memory); /// @dev Retrieves the IDs of all supported tiers. /// Note that the core protocol requires the number of tiers to be smaller /// than 256. In reality, this number should be much smaller. /// @return The ids of the tiers. function getTierIds() external view returns (uint16[] memory); /// @dev Determines the minimal tier for a block based on a random input. /// @param proposer The address of the block proposer. /// @param rand A pseudo-random number. /// @return The tier id. function getMinTier(address proposer, uint256 rand) external view returns (uint16); } /// @dev Tier ID cannot be zero! library LibTiers { /// @notice Optimistic tier ID. uint16 public constant TIER_OPTIMISTIC = 100; /// @notice SGX tier ID. uint16 public constant TIER_SGX = 200; /// @notice SGX tier ID. uint16 public constant TIER_SGX2 = 200; // @notice ZKVM risc0 tier ID uint16 public constant TIER_ZKVM_RISC0 = 290; /// @notice SGX + ZKVM tier ID. uint16 public constant TIER_SGX_ZKVM = 300; /// @notice Guardian tier ID with minority approval. uint16 public constant TIER_GUARDIAN_MINORITY = 900; /// @notice Guardian tier ID with majority approval. uint16 public constant TIER_GUARDIAN = 1000; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title ITierRouter /// @notice Defines interface to return an ITierProvider /// @custom:security-contact [email protected] interface ITierRouter { /// @dev Returns the address of the TierProvider for a given block. /// @param blockId ID of the block. /// @return The address of the corresponding TierProvider. function getProvider(uint256 blockId) external view returns (address); }
// 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); }
// 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); }
// 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 } } }
// 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; }
// 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); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "solady/=node_modules/solady/", "forge-std/=node_modules/forge-std/", "ds-test/=node_modules/ds-test/src/", "p256-verifier/=node_modules/p256-verifier/", "optimism/=node_modules/optimism/", "risc0-ethereum/=node_modules/risc0-ethereum/", "sp1-contracts/=node_modules/sp1-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
[{"inputs":[],"name":"ETH_TRANSFER_FAILED","type":"error"},{"inputs":[],"name":"FUNC_NOT_IMPLEMENTED","type":"error"},{"inputs":[],"name":"INVALID_PAUSE_STATUS","type":"error"},{"inputs":[],"name":"L1_ALREADY_CONTESTED","type":"error"},{"inputs":[],"name":"L1_ALREADY_PROVED","type":"error"},{"inputs":[],"name":"L1_BLOB_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"L1_BLOB_NOT_FOUND","type":"error"},{"inputs":[],"name":"L1_BLOCK_MISMATCH","type":"error"},{"inputs":[],"name":"L1_BLOCK_MISMATCH","type":"error"},{"inputs":[],"name":"L1_CANNOT_CONTEST","type":"error"},{"inputs":[],"name":"L1_INVALID_BLOCK_ID","type":"error"},{"inputs":[],"name":"L1_INVALID_GENESIS_HASH","type":"error"},{"inputs":[],"name":"L1_INVALID_PAUSE_STATUS","type":"error"},{"inputs":[],"name":"L1_INVALID_SIG","type":"error"},{"inputs":[],"name":"L1_INVALID_TIER","type":"error"},{"inputs":[],"name":"L1_INVALID_TRANSITION","type":"error"},{"inputs":[],"name":"L1_NOT_ASSIGNED_PROVER","type":"error"},{"inputs":[],"name":"L1_PROVING_PAUSED","type":"error"},{"inputs":[],"name":"L1_RECEIVE_DISABLED","type":"error"},{"inputs":[],"name":"L1_TOO_MANY_BLOCKS","type":"error"},{"inputs":[],"name":"L1_TRANSITION_ID_ZERO","type":"error"},{"inputs":[],"name":"L1_TRANSITION_NOT_FOUND","type":"error"},{"inputs":[],"name":"L1_UNEXPECTED_PARENT","type":"error"},{"inputs":[],"name":"L1_UNEXPECTED_TRANSITION_ID","type":"error"},{"inputs":[],"name":"REENTRANT_CALL","type":"error"},{"inputs":[],"name":"RESOLVER_DENIED","type":"error"},{"inputs":[],"name":"RESOLVER_INVALID_MANAGER","type":"error"},{"inputs":[],"name":"RESOLVER_UNEXPECTED_CHAINID","type":"error"},{"inputs":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"RESOLVER_ZERO_ADDR","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_VALUE","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"indexed":true,"internalType":"address","name":"assignedProver","type":"address"},{"indexed":false,"internalType":"uint96","name":"livenessBond","type":"uint96"},{"components":[{"internalType":"bytes32","name":"l1Hash","type":"bytes32"},{"internalType":"bytes32","name":"difficulty","type":"bytes32"},{"internalType":"bytes32","name":"blobHash","type":"bytes32"},{"internalType":"bytes32","name":"extraData","type":"bytes32"},{"internalType":"bytes32","name":"depositsHash","type":"bytes32"},{"internalType":"address","name":"coinbase","type":"address"},{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"l1Height","type":"uint64"},{"internalType":"uint16","name":"minTier","type":"uint16"},{"internalType":"bool","name":"blobUsed","type":"bool"},{"internalType":"bytes32","name":"parentMetaHash","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"}],"indexed":false,"internalType":"struct TaikoData.BlockMetadata","name":"meta","type":"tuple"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint64","name":"id","type":"uint64"}],"indexed":false,"internalType":"struct TaikoData.EthDeposit[]","name":"depositsProcessed","type":"tuple[]"}],"name":"BlockProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"indexed":true,"internalType":"address","name":"prover","type":"address"},{"indexed":false,"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"tier","type":"uint16"}],"name":"BlockVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BondCredited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BondDebited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"txList","type":"bytes"}],"name":"CalldataTxList","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"ProvingPaused","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint64","name":"numBlocks","type":"uint64"},{"internalType":"uint64","name":"lastVerifiedBlockId","type":"uint64"},{"internalType":"bool","name":"provingPaused","type":"bool"},{"internalType":"uint8","name":"__reservedB1","type":"uint8"},{"internalType":"uint16","name":"__reservedB2","type":"uint16"},{"internalType":"uint32","name":"__reservedB3","type":"uint32"},{"internalType":"uint64","name":"lastUnpausedAt","type":"uint64"}],"indexed":false,"internalType":"struct TaikoData.SlotB","name":"slotB","type":"tuple"}],"name":"StateVariablesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"parentHash","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"graffiti","type":"bytes32"}],"indexed":false,"internalType":"struct TaikoData.Transition","name":"tran","type":"tuple"},{"indexed":false,"internalType":"address","name":"contester","type":"address"},{"indexed":false,"internalType":"uint96","name":"contestBond","type":"uint96"},{"indexed":false,"internalType":"uint16","name":"tier","type":"uint16"}],"name":"TransitionContested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"components":[{"internalType":"bytes32","name":"parentHash","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"graffiti","type":"bytes32"}],"indexed":false,"internalType":"struct TaikoData.Transition","name":"tran","type":"tuple"},{"indexed":false,"internalType":"address","name":"prover","type":"address"},{"indexed":false,"internalType":"uint96","name":"validityBond","type":"uint96"},{"indexed":false,"internalType":"uint16","name":"tier","type":"uint16"}],"name":"TransitionProved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addressManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"bondBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositBond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"}],"name":"getBlock","outputs":[{"components":[{"internalType":"bytes32","name":"metaHash","type":"bytes32"},{"internalType":"address","name":"assignedProver","type":"address"},{"internalType":"uint96","name":"livenessBond","type":"uint96"},{"internalType":"uint64","name":"blockId","type":"uint64"},{"internalType":"uint64","name":"proposedAt","type":"uint64"},{"internalType":"uint64","name":"proposedIn","type":"uint64"},{"internalType":"uint32","name":"nextTransitionId","type":"uint32"},{"internalType":"uint32","name":"verifiedTransitionId","type":"uint32"}],"internalType":"struct TaikoData.Block","name":"blk_","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint64","name":"chainId","type":"uint64"},{"internalType":"uint64","name":"blockMaxProposals","type":"uint64"},{"internalType":"uint64","name":"blockRingBufferSize","type":"uint64"},{"internalType":"uint64","name":"maxBlocksToVerify","type":"uint64"},{"internalType":"uint32","name":"blockMaxGasLimit","type":"uint32"},{"internalType":"uint96","name":"livenessBond","type":"uint96"},{"internalType":"uint8","name":"stateRootSyncInternal","type":"uint8"},{"internalType":"bool","name":"checkEOAForCalldataDA","type":"bool"}],"internalType":"struct TaikoData.Config","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getLastSyncedBlock","outputs":[{"internalType":"uint64","name":"blockId_","type":"uint64"},{"internalType":"bytes32","name":"blockHash_","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastVerifiedBlock","outputs":[{"internalType":"uint64","name":"blockId_","type":"uint64"},{"internalType":"bytes32","name":"blockHash_","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStateVariables","outputs":[{"components":[{"internalType":"uint64","name":"genesisHeight","type":"uint64"},{"internalType":"uint64","name":"genesisTimestamp","type":"uint64"},{"internalType":"uint64","name":"lastSyncedBlockId","type":"uint64"},{"internalType":"uint64","name":"lastSynecdAt","type":"uint64"}],"internalType":"struct TaikoData.SlotA","name":"","type":"tuple"},{"components":[{"internalType":"uint64","name":"numBlocks","type":"uint64"},{"internalType":"uint64","name":"lastVerifiedBlockId","type":"uint64"},{"internalType":"bool","name":"provingPaused","type":"bool"},{"internalType":"uint8","name":"__reservedB1","type":"uint8"},{"internalType":"uint16","name":"__reservedB2","type":"uint16"},{"internalType":"uint32","name":"__reservedB3","type":"uint32"},{"internalType":"uint64","name":"lastUnpausedAt","type":"uint64"}],"internalType":"struct TaikoData.SlotB","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"uint32","name":"_tid","type":"uint32"}],"name":"getTransition","outputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"address","name":"prover","type":"address"},{"internalType":"uint96","name":"validityBond","type":"uint96"},{"internalType":"address","name":"contester","type":"address"},{"internalType":"uint96","name":"contestBond","type":"uint96"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint16","name":"tier","type":"uint16"},{"internalType":"uint8","name":"__reserved1","type":"uint8"}],"internalType":"struct TaikoData.TransitionState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"bytes32","name":"_parentHash","type":"bytes32"}],"name":"getTransition","outputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"address","name":"prover","type":"address"},{"internalType":"uint96","name":"validityBond","type":"uint96"},{"internalType":"address","name":"contester","type":"address"},{"internalType":"uint96","name":"contestBond","type":"uint96"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint16","name":"tier","type":"uint16"},{"internalType":"uint8","name":"__reserved1","type":"uint8"}],"internalType":"struct TaikoData.TransitionState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"}],"name":"getVerifiedBlockProver","outputs":[{"internalType":"address","name":"prover_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"impl","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inNonReentrant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_addressManager","type":"address"},{"internalType":"bytes32","name":"_genesisBlockHash","type":"bytes32"},{"internalType":"bool","name":"_toPause","type":"bool"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"init2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastUnpausedAt","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"pauseProving","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_params","type":"bytes"},{"internalType":"bytes","name":"_txList","type":"bytes"}],"name":"proposeBlock","outputs":[{"components":[{"internalType":"bytes32","name":"l1Hash","type":"bytes32"},{"internalType":"bytes32","name":"difficulty","type":"bytes32"},{"internalType":"bytes32","name":"blobHash","type":"bytes32"},{"internalType":"bytes32","name":"extraData","type":"bytes32"},{"internalType":"bytes32","name":"depositsHash","type":"bytes32"},{"internalType":"address","name":"coinbase","type":"address"},{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"l1Height","type":"uint64"},{"internalType":"uint16","name":"minTier","type":"uint16"},{"internalType":"bool","name":"blobUsed","type":"bool"},{"internalType":"bytes32","name":"parentMetaHash","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"}],"internalType":"struct TaikoData.BlockMetadata","name":"meta_","type":"tuple"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint64","name":"id","type":"uint64"}],"internalType":"struct TaikoData.EthDeposit[]","name":"deposits_","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"bytes","name":"_input","type":"bytes"}],"name":"proveBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"bytes32","name":"_name","type":"bytes32"},{"internalType":"bool","name":"_allowZeroAddress","type":"bool"}],"name":"resolve","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_name","type":"bytes32"},{"internalType":"bool","name":"_allowZeroAddress","type":"bool"}],"name":"resolve","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"bytes32","name":"__reserve1","type":"bytes32"},{"components":[{"internalType":"uint64","name":"genesisHeight","type":"uint64"},{"internalType":"uint64","name":"genesisTimestamp","type":"uint64"},{"internalType":"uint64","name":"lastSyncedBlockId","type":"uint64"},{"internalType":"uint64","name":"lastSynecdAt","type":"uint64"}],"internalType":"struct TaikoData.SlotA","name":"slotA","type":"tuple"},{"components":[{"internalType":"uint64","name":"numBlocks","type":"uint64"},{"internalType":"uint64","name":"lastVerifiedBlockId","type":"uint64"},{"internalType":"bool","name":"provingPaused","type":"bool"},{"internalType":"uint8","name":"__reservedB1","type":"uint8"},{"internalType":"uint16","name":"__reservedB2","type":"uint16"},{"internalType":"uint32","name":"__reservedB3","type":"uint32"},{"internalType":"uint64","name":"lastUnpausedAt","type":"uint64"}],"internalType":"struct TaikoData.SlotB","name":"slotB","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_maxBlocksToVerify","type":"uint64"}],"name":"verifyBlocks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawBond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523060805234801562000014575f80fd5b506200001f6200002f565b620000296200002f565b620000ed565b5f54610100900460ff16156200009b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614620000eb575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615e52620001225f395f8181610a5201528181610a9201528181610b9801528181610bd80152610c530152615e525ff3fe6080604052600436106101ff575f3560e01c806379ba509711610113578063c3daab961161009d578063e30c39781161006d578063e30c3978146106b4578063ef16e845146106d1578063f2fde38b146106f2578063fd257e2914610711578063ff00c39114610730575f80fd5b8063c3daab9614610615578063c3f909d414610634578063dde89cf514610655578063e07baba614610677575f80fd5b80638da5cb5b116100e35780638da5cb5b146104c65780639413caa9146104e3578063a86f9d9e146104f7578063a9c2c83514610516578063c19d93fb14610535575f80fd5b806379ba50971461046b5780638456cb591461047f5780638778209d146104935780638abf6077146104b2575f80fd5b80633f4ba83a11610194578063563479a511610164578063563479a5146103c05780635c975abb146103ec5780635fa15e791461040c5780636074b8c114610438578063715018a614610457575f80fd5b80633f4ba83a146103585780634dcb05f91461036c5780634f1ef2861461038b57806352d1902d1461039e575f80fd5b80633075db56116101cf5780633075db56146102bf5780633659cfe6146102e35780633ab76e9f146103025780633eb6b8cf14610339575f80fd5b8063069489a21461022f57806310d008bd1461024357806326af79861461026257806329d1b62f146102a0575f80fd5b3661022b5761020c61074f565b61022957604051630d28633960e01b815260040160405180910390fd5b005b5f80fd5b34801561023a575f80fd5b50610229610763565b34801561024e575f80fd5b5061022961025d366004614c1e565b61081a565b34801561026d575f80fd5b50610276610932565b604080516001600160401b0390941684526020840192909252908201526060015b60405180910390f35b3480156102ab575f80fd5b506102296102ba366004614ca3565b610965565b3480156102ca575f80fd5b506102d361074f565b6040519015158152602001610297565b3480156102ee575f80fd5b506102296102fd366004614cf3565b610a48565b34801561030d575f80fd5b50609754610321906001600160a01b031681565b6040516001600160a01b039091168152602001610297565b348015610344575f80fd5b50610321610353366004614d0e565b610b0f565b348015610363575f80fd5b50610229610b25565b348015610377575f80fd5b50610229610386366004614d4b565b610b50565b610229610399366004614e7e565b610b8e565b3480156103a9575f80fd5b506103b2610c47565b604051908152602001610297565b3480156103cb575f80fd5b506103df6103da366004614edd565b610cf8565b6040516102979190614f0e565b3480156103f7575f80fd5b506102d360c954610100900460ff1660021490565b348015610417575f80fd5b5061042b610426366004614fd9565b610dbc565b6040516102979190614ff2565b348015610443575f80fd5b50610321610452366004614fd9565b610ea3565b348015610462575f80fd5b50610229610eb7565b348015610476575f80fd5b50610229610eca565b34801561048a575f80fd5b50610229610f41565b34801561049e575f80fd5b506102296104ad366004614fd9565b610f54565b3480156104bd575f80fd5b5061032161103f565b3480156104d1575f80fd5b506033546001600160a01b0316610321565b3480156104ee575f80fd5b5061027661104d565b348015610502575f80fd5b5061032161051136600461508a565b61106f565b348015610521575f80fd5b506103b2610530366004614cf3565b61107b565b348015610540575f80fd5b5060fe54604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c0830152610606929183565b6040516102979392919061511a565b348015610620575f80fd5b5061022961062f366004614d4b565b611099565b34801561063f575f80fd5b506106486110d7565b604051610297919061516a565b348015610660575f80fd5b5061066961116e565b6040516102979291906151f8565b348015610682575f80fd5b5060c95461069c906201000090046001600160401b031681565b6040516001600160401b039091168152602001610297565b3480156106bf575f80fd5b506065546001600160a01b0316610321565b6106e46106df366004615242565b611258565b6040516102979291906153f5565b3480156106fd575f80fd5b5061022961070c366004614cf3565b611376565b34801561071c575f80fd5b506103df61072b36600461541f565b6113e7565b34801561073b575f80fd5b5061022961074a366004615447565b611403565b5f600261075a611418565b60ff1614905090565b61076b611457565b5f54600290610100900460ff1615801561078b57505f5460ff8083169116105b6107b05760405162461bcd60e51b81526004016107a790615462565b60405180910390fd5b5f8054610100805466ffffffffffffff60881b1916815560fe83905561ff001960ff851661ffff199093168317909117169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b61082e60c954610100900460ff1660021490565b1561084c5760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610878576040516333018e5560e11b815260040160405180910390fd5b6002610882611418565b60ff16036108a35760405163dfc60d8560e01b815260040160405180910390fd5b6108ad60026114b1565b5f6108b66110d7565b90506108c760fb82308787876114f9565b6108d281855f612078565b156108e8576108e860fb823084606001516120e7565b506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b9061091b90610100906154b0565b60405180910390a161092d60016114b1565b505050565b61010054600160401b90046001600160401b03165f8061095b60fb6109556110d7565b85612976565b9394909392509050565b5f54610100900460ff161580801561098357505f54600160ff909116105b8061099c5750303b15801561099c57505f5460ff166001145b6109b85760405162461bcd60e51b81526004016107a790615462565b5f805460ff1916600117905580156109d9575f805461ff0019166101001790555b6109e385856129ef565b6109ee60fb84612a29565b81156109fc576109fc612b71565b8015610a41575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610a905760405162461bcd60e51b81526004016107a790615518565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610ac2612be8565b6001600160a01b031614610ae85760405162461bcd60e51b81526004016107a790615564565b610af181612c03565b604080515f80825260208201909252610b0c91839190612c0b565b50565b5f610b1b848484612d75565b90505b9392505050565b610b2d612e66565b61010080546001600160c01b0316600160c01b426001600160401b031602179055565b610b6460c954610100900460ff1660021490565b15610b825760405163bae6e2a960e01b815260040160405180910390fd5b610b0c60fb3083612e78565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610bd65760405162461bcd60e51b81526004016107a790615518565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c08612be8565b6001600160a01b031614610c2e5760405162461bcd60e51b81526004016107a790615564565b610c3782612c03565b610c4382826001612c0b565b5050565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610ce65760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016107a7565b505f80516020615dd683398151915290565b610d00614930565b610d1460fb610d0d6110d7565b8585612f1e565b6040805161014081018252825481526001830154602082015260028301549181019190915260038201546001600160a01b0380821660608401526001600160601b03600160a01b9283900481166080850152600485015491821660a08501529190041660c08201526005909101546001600160401b03811660e083015261ffff600160401b82041661010083015260ff600160501b9091041661012082015290505b92915050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152610e0f60fb610e096110d7565b84612fac565b5060408051610100810182528254815260018301546001600160a01b03811660208301526001600160601b03600160a01b90910416918101919091526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b82041660a083015263ffffffff600160c01b8204811660c0840152600160e01b9091041660e082015292915050565b5f610db660fb610eb16110d7565b8461300c565b610ebf611457565b610ec85f613064565b565b60655433906001600160a01b03168114610f385760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016107a7565b610b0c81613064565b610f49612b71565b610ec833600161307d565b610f6860c954610100900460ff1660021490565b15610f865760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610fb2576040516333018e5560e11b815260040160405180910390fd5b6002610fbc611418565b60ff1603610fdd5760405163dfc60d8560e01b815260040160405180910390fd5b610fe760026114b1565b610ffb60fb610ff46110d7565b30846120e7565b6040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b9061102d90610100906154b0565b60405180910390a1610b0c60016114b1565b5f611048612be8565b905090565b60ff54600160801b90046001600160401b03165f8061095b60fb6109556110d7565b5f610b1e468484612d75565b6001600160a01b0381165f9081526101016020526040812054610db6565b6110ad60c954610100900460ff1660021490565b156110cb5760405163bae6e2a960e01b815260040160405180910390fd5b610b0c60fb30836130fc565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915250604080516101008101825262028c6181526204f1a060208201526204f3a091810191909152601060608201819052630e4e1c0060808301526806c6b935b8bbd4000060a083015260c0820152600160e082015290565b604080516080810182525f808252602082018190529181018290526060810191909152611199614983565b5050604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015291565b6112606149be565b606061127660c954610100900460ff1660021490565b156112945760405163bae6e2a960e01b815260040160405180910390fd5b600261129e611418565b60ff16036112bf5760405163dfc60d8560e01b815260040160405180910390fd5b6112c960026114b1565b5f6112d26110d7565b90506112e460fb82308a8a8a8a613160565b60c082015191945092506112fb9082906001612078565b8015611312575061010054600160801b900460ff16155b156113285761132860fb823084606001516120e7565b506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b9061135b90610100906154b0565b60405180910390a161136d60016114b1565b94509492505050565b61137e611457565b606580546001600160a01b0383166001600160a01b031990911681179091556113af6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6113ef614930565b610d1460fb6113fc6110d7565b85856138fe565b61140d338261307d565b610b0c60fb8261397b565b5f61142246613a28565b1561144d57507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b6033546001600160a01b03163314610ec85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107a7565b6114ba46613a28565b156114e557807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b5f808061150884860186615684565b9250925092508260c001516001600160401b0316866001600160401b03161461154457604051638a1c400f60e01b815260040160405180910390fd5b8151158061155457506020820151155b8061156157506040820151155b1561157f576040516317eddea160e11b815260040160405180910390fd5b611587614a31565b6040805160e08101825260058c01546001600160401b038082168352600160401b820481166020840190815260ff600160801b84048116151595850195909552600160881b8304909416606084015261ffff600160901b830416608084015263ffffffff600160a01b83041660a0840152600160c01b909104811660c0808401919091529184529151908601519082169116111580611639575080515160c08501516001600160401b03918216911610155b1561165757604051638a1c400f60e01b815260040160405180910390fd5b88604001518460c0015161166b91906157cc565b6001600160401b0390811660e083018190525f90815260208c9052604090206002810154909116610100830181905260c08b01516116ae9160ff90911690613a55565b156116be57604084015160a08301525b60018101546001600160a01b0316608083018190526116ec576101a08501516001600160a01b031660808301525b6001810154600160a01b90046001600160601b031660c083810191909152815460608401528501516101008301516001600160401b039182169116141580611740575061173885613a82565b826060015114155b1561175e57604051632ec3485560e11b815260040160405180910390fd5b611766614930565b6117728c838786613ab1565b63ffffffff909116610120850152845190915061ffff1615806117a4575085610140015161ffff16845f015161ffff16105b806117be575080610100015161ffff16845f015161ffff16105b156117dc57604051631a32f51360e01b815260040160405180910390fd5b604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015611835573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185991906157f1565b610100850151604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa1580156118b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118d491906157f1565b865160405163576c3de760e01b815261ffff90911660048201529091506001600160a01b0382169063576c3de79060240160c060405180830381865afa158015611920573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119449190615822565b602086015261014088015160405163576c3de760e01b815261ffff90911660048201526001600160a01b0382169063576c3de79060240160c060405180830381865afa158015611996573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ba9190615822565b856040018190525050506119f88160e001516001600160401b0316845f015160c001516001600160401b031685604001516080015161ffff16613c62565b156101808401526020830151604001516001600160601b031615801590611a2a575060a08101516001600160a01b0316155b8015611a41575082610120015163ffffffff166001145b8015611a54575061010081015161ffff16155b8015611a6257508261018001515b15611a9d5782608001516001600160a01b0316336001600160a01b031614611a9d57604051632185a2ad60e21b815260040160405180910390fd5b60208301515115611c0757602083015151604051635437cecf60e11b815260048101919091525f60248201819052906001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015611afb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b1f91906157f1565b90505f82610100015161ffff16865f015161ffff16148015611b5157506020850151604001516001600160601b031615155b6040805160e08101825260608089015182528b8301516020830152338284018190526101008a01516001600160401b03169183019190915283151560808301526101608c0151151560a083015260c0820152905163043d132d60e31b8152919250906001600160a01b038416906321e8996890611bd69084908c908c9060040161591b565b5f604051808303815f87803b158015611bed575f80fd5b505af1158015611bff573d5f803e3d5ffd5b505050505050505b602080840151604001516001600160601b0316156101608501528181015190860151148015611c3d575080604001518360a00151145b15156101a0840152610100810151845161ffff91821691161115611cc657611c6a8c8b8484898989613c7f565b8261010001516001600160401b03167fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f8633866020015160200151885f0151604051611cb994939291906159b3565b60405180910390a2611ebf565b826101a0015115611cea57604051639d49773160e01b815260040160405180910390fd5b82610160015115611dab5760208084015101516001600160601b031615611d1357611d13615a06565b60808101516001600160601b0316158015611d39575060a08101516001600160a01b0316155b611d4557611d45615a06565b33606082018190526020808701519083015260a0840151604080840191909152610100850151865191516001600160401b03909116927fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f92611cb9928a92915f916159b3565b60a08101516001600160a01b031615611dd7576040516382ef169960e01b815260040160405180910390fd5b611e0c8160e001516001600160401b0316845f015160c001516001600160401b031685602001516060015162ffffff16613c62565b15611e2a5760405163378b1eff60e21b815260040160405180910390fd5b611e478c8b338660200151604001516001600160601b0316613ebf565b6020830180516040908101516001600160601b031660c08401523360a084018190526101008601519251820151875192516001600160401b03909416937fb4c0a86c1ff239277697775b1e91d3375fd3a5ef6b345aa4e2f6001c890558f693611eb6938b9390929091906159b3565b60405180910390a25b428160e001906001600160401b031690816001600160401b031681525050808c6002015f8560e001516001600160401b03166001600160401b031681526020019081526020015f205f85610120015163ffffffff1663ffffffff1681526020019081526020015f205f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160030160146101000a8154816001600160601b0302191690836001600160601b0316021790555060a0820151816004015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c08201518160040160146101000a8154816001600160601b0302191690836001600160601b0316021790555060e0820151816005015f6101000a8154816001600160401b0302191690836001600160401b031602179055506101008201518160050160086101000a81548161ffff021916908361ffff16021790555061012082015181600501600a6101000a81548160ff021916908360ff160217905550905050505050505050505050505050565b5f83606001516001600160401b03165f0361209457505f610b1e565b6060840151677fffffffffffffff600191821c169081116120b9576001915050610b1e565b826120c857600181901c6120ca565b5f5b6120dd826001600160401b038716615a1a565b1495945050505050565b6001600160401b03811615612970576120fe614b03565b6040805160e08101825260058701546001600160401b038082168352600160401b82048116602080850191825260ff600160801b85048116151586880152600160881b850416606086015261ffff600160901b850416608086015263ffffffff600160a01b85041660a0860152600160c01b909304821660c0850152928552915190911690830181905290850151612195916157cc565b6001600160401b0390811660408084018290525f9182526020888152912090830151600282015491929182169116146121e157604051632ec3485560e11b815260040160405180910390fd5b6002810154600160e01b900463ffffffff1660a08301819052608083018190525f036122205760405163d4345b9760e01b815260040160405180910390fd5b6040808301516001600160401b039081165f908152600289016020908152838220608087015163ffffffff168352815292902060019081015460e086015291840180519092011690525b81515160208301516001600160401b0391821691161080156122a15750826001600160401b031682606001516001600160401b0316105b156126b05784604001516001600160401b031682602001516001600160401b0316816122cf576122cf6157b8565b066001600160401b0390811660408481018290525f91825260208981529120908401516002820154919350821691161461231c57604051632ec3485560e11b815260040160405180910390fd5b612330868284604001518560e00151613fbe565b63ffffffff1660808301819052156126b0576040828101516001600160401b03165f908152600288016020908152828220608086015163ffffffff1683529052206005810154600160401b900461ffff1660c084015260048101546001600160a01b03161561239f57506126b0565b6101808301516001600160a01b031661243c57604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201526001600160a01b0386169063a86f9d9e90604401602060405180830381865afa158015612408573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061242c91906157f1565b6001600160a01b03166101808401525b6101808301516020840151604051635c42d07960e01b81526001600160401b0390911660048201525f916001600160a01b031690635c42d07990602401602060405180830381865afa158015612494573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124b891906157f1565b60c085015160405163576c3de760e01b815261ffff90911660048201526001600160a01b03919091169063576c3de79060240160c060405180830381865afa158015612506573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061252a9190615822565b606001516005830154855160c00151919250612558916001600160401b03918216911662ffffff8416613c62565b6125635750506126b0565b50608083015163ffffffff1660a0840152600181015460e084015260038101546001600160a01b03811661016085018190526125b191899190600160a01b90046001600160601b0316614097565b8261016001516001600160a01b031683602001516001600160401b03167fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2898560e001515f8760c0015160405161261e93929190928352602083019190915261ffff16604082015260600190565b60405180910390a36126448660c0015160ff1684602001516001600160401b0316613a55565b15612684576002810154801561268257610100840181905260208401516001600160401b0316610120850152608084015163ffffffff166101408501525b505b506020820180516001600160401b0360019182018116909252606084018051909101909116905261226a565b60608201516001600160401b03161561296d57606082015182516020015160408701519101906001600160401b03908116908216816126f1576126f16157b8565b6001600160401b039190068116604080860182905260058a018054938516600160401b026fffffffffffffffff0000000000000000199094169390931790925560a08501515f91825260208a9052919020600201805463ffffffff909216600160e01b026001600160e01b039092169190911790556101008301511561296b576101208301516004880180546fffffffffffffffffffffffffffffffff16600160801b6001600160401b039384169081026001600160c01b031691909117600160c01b4285160217909155908216146128375785604001516001600160401b03168361012001516001600160401b0316816127ee576127ee6157b8565b066001600160401b031660408481018290526101408501515f92835260208a9052912060020180546001600160e01b0316600160e01b63ffffffff909316929092029190911790555b604051635437cecf60e11b81526d7369676e616c5f7365727669636560901b60048201525f60248201526001600160a01b0386169063a86f9d9e90604401602060405180830381865afa158015612890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128b491906157f1565b86516101208501516101008601516040516313e4299d60e21b81526001600160401b0393841660048201527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da169602482015292909116604483015260648201526001600160a01b039190911690634f90a674906084016020604051808303815f875af1158015612945573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129699190615a2d565b505b505b50505b50505050565b5f805f80612985878787612fac565b60028201549193509150600160e01b900463ffffffff16156129e5576001600160401b0381165f90815260028881016020908152604080842086840154600160e01b900463ffffffff168552909152909120600181015491015490945092505b5050935093915050565b806001600160a01b038116612a175760405163538ba4f960e01b815260040160405180910390fd5b612a2083614108565b61092d82614166565b5f819003612a4a5760405163d6d0f75560e01b815260040160405180910390fd5b600482018054426001600160401b03908116600160401b81026001600160801b031990931643929092169190911782179092556005808501805467ffffffffffffffff1990811660019081179092555f80805260208881526040808320600280820180546001600160e01b037fffffffff00000000ffffffffffffffff0000000000000000ffffffffffffffff909116909a17600160c11b1799909916600160e01b17909855858155968a01825280832085845282528083209485018990556003850180546001600160a01b031916905594840180549093169096179091558251868152948501819052918401829052919281907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a350505050565b612b8560c954610100900460ff1660021490565b15612ba35760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b5f80516020615dd6833981519152546001600160a01b031690565b610b0c611457565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612c3e5761092d836141d6565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612c98575060408051601f3d908101601f19168201909252612c9591810190615a2d565b60015b612cfb5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016107a7565b5f80516020615dd68339815191528114612d695760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016107a7565b5061092d838383614271565b6097545f906001600160a01b031680612da157604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0386166004820152602481018590526001600160a01b038216906328f713cc90604401602060405180830381865afa158015612df3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e1791906157f1565b915082158015612e2e57506001600160a01b038216155b15612e5e57604051632b0d65db60e01b81526001600160401b0386166004820152602481018590526044016107a7565b509392505050565b612e6e614295565b610ec8335f61307d565b335f90815260068401602052604081208054839290612e98908490615a58565b90915550612ea790508261431f565b6040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b0391909116906323b872dd906064015b6020604051808303815f875af1158015612efa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129709190615a6b565b5f805f612f2c878787612fac565b915091508363ffffffff165f1480612f595750600282015463ffffffff600160c01b909104811690851610155b15612f775760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b03165f908152600287016020908152604080832063ffffffff8716845290915290209150505b949350505050565b5f80836040015183612fbe91906157cc565b6001600160401b038181165f908152602088905260409020600281015490945091925084811691161461300457604051638a1c400f60e01b815260040160405180910390fd5b935093915050565b5f80613019858585612fac565b506002810154909150600160e01b900463ffffffff165f819003613041575f92505050610b1e565b61304d86868684612f1e565b600301546001600160a01b03169695505050505050565b606580546001600160a01b0319169055610b0c8161439c565b6d636861696e5f7761746368646f6760901b6130a16033546001600160a01b031690565b6001600160a01b0316336001600160a01b0316141580156130de57506130c881600161106f565b6001600160a01b0316336001600160a01b031614155b1561092d57604051630d85cccf60e11b815260040160405180910390fd5b335f9081526006840160205260408120805483929061311c908490615a86565b9091555061312b90508261431f565b60405163a9059cbb60e01b8152336004820152602481018390526001600160a01b03919091169063a9059cbb90604401612ede565b6131686149be565b6060613172614b75565b61317e86880188615b75565b602080830182905201516001600160a01b03166131a057602080820151339101525b6040805160e08101825260058c01546001600160401b038082168352600160401b82048116602080850191825260ff600160801b85048116151596860196909652600160881b8404909516606085015261ffff600160901b840416608085015263ffffffff600160a01b84041660a0850152600160c01b9092041660c0830152908352908a015190516132339190615c35565b61323e906001615c35565b8151516001600160401b0391821691161061326c576040516351ec7d5360e01b815260040160405180910390fd5b60408901518151518b915f9161328490600190615c55565b61328e91906157cc565b6001600160401b0316815260208082019290925260409081015f20549083015281015160600151158015906132cf5750806020015160600151816040015114155b156132ed57604051630d41ec8760e11b815260040160405180910390fd5b604080516101c0810182525f194301804082525f6020808401829052838501829052858101805186015160608601527f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd6080808701919091529051909101516001600160a01b031660a08501528551516001600160401b0390811660c0860152908e015163ffffffff1660e08501524281166101008501529091166101208301526101408201528515610160820181905291830151610180820152336101a082015293501561340a576133bf46613a28565b6133dc5760405163df9969ef60e01b815260040160405180910390fd5b5f804960408501819052900361340557604051639e7e2ddd60e01b815260040160405180910390fd5b6134c7565b848460405161341a929190615c75565b60408051918290039091209084015260e089015180156134615750336001600160a01b03166134558460400151836020015160a001516143ed565b6001600160a01b031614155b1561347f5760405163f6ee3bdb60e01b815260040160405180910390fd5b8260c001516001600160401b03167fa07bc5e8f00f6065c8727821591c519efd2348e4ff0c26560a85592e85b6f41886866040516134be929190615c84565b60405180910390a25b8051516040805144602082015260c09290921b6001600160c01b0319169082015243604882015260680160408051808303601f1901815291815281516020928301209185019190915251635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b038a169063a86f9d9e90604401602060405180830381865afa158015613567573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061358b91906157f1565b825151604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa1580156135df573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061360391906157f1565b6101a086015160208701516040516352c5c56b60e01b81526001600160a01b03928316600482015260248101919091529192508216906352c5c56b90604401602060405180830381865afa15801561365d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136819190615cb2565b61ffff1661014086015250506040805161010081019091525f90806136a586613a82565b81525f6020820181905260a0808e01516001600160601b03166040808501919091528651516001600160401b0390811660608601526101008a015181166080860152431691840191909152600160c084015260e0909201819052908c015184515192935083928e9291613717916157cc565b6001600160401b03908116825260208083019390935260409182015f208451815592840151918401516001600160a01b03909216600160a01b6001600160601b039384160217600180850191909155606085015160029094018054608087015160a08089015160c08a015160e0909a01519887166001600160801b031990941693909317600160401b92871692909202919091176bffffffffffffffffffffffff60801b1916600160801b9286169290920263ffffffff60c01b191691909117600160c01b63ffffffff98891602176001600160e01b0316600160e01b97909616969096029490941790935560058f01805467ffffffffffffffff19811690831690940190911692909217909155908b0151613839918d918c91339116613ebf565b341580159061384757504115155b15613856576138564134614407565b604080515f8082526020820190925290613896565b604080516060810182525f80825260208083018290529282015282525f1990920191018161386b5790505b509250336001600160a01b03168460c001516001600160401b03167fcda4e564245eb15494bc6da29f6a42e1941cf57f5314bf35bab8a1fca0a9c60a8c60a0015187876040516138e893929190615ccd565b60405180910390a3505097509795505050505050565b5f805f61390c878787612fac565b915091505f61391d88848488613fbe565b90508063ffffffff165f036139455760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b039091165f908152600288016020908152604080832063ffffffff909416835292905220915050949350505050565b6005820154811515600160801b90910460ff161515036139ae5760405163689d009d60e11b815260040160405180910390fd5b60058201805460ff60801b1916600160801b83151502179055806139ef576005820180546001600160c01b0316600160c01b426001600160401b0316021790555b60405181151581527fed64db85835d07c3c990b8ebdd55e32d64e5ed53143b6ef2179e7bfaf17ddc3b9060200160405180910390a15050565b5f6001821480613a39575061426882145b80613a46575062aa36a782145b80610db65750610db682614412565b5f60018311613a6657506001610db6565b60018303838381613a7957613a796157b8565b06149392505050565b5f81604051602001613a949190615cfd565b604051602081830303815290604052805190602001209050919050565b5f613aba614930565b613acd86868560e00151875f0151613fbe565b91508163ffffffff165f03613b8e57600285018054600163ffffffff600160c01b80840482168381019092160263ffffffff60c01b1990931692909217928390556001600160401b03600160401b9093049290921660e08401529250829003613b4c578351815260808301516001600160a01b0316606082015261136d565b6101008301516001600160401b03165f9081526001870160209081526040808320875184529091529020805463ffffffff191663ffffffff841617905561136d565b5060e0808301516001600160401b039081165f90815260028089016020908152604080842063ffffffff8816855282529283902083516101408101855281548152600182015492810192909252918201549281019290925260038101546001600160a01b0380821660608501526001600160601b03600160a01b9283900481166080860152600484015491821660a08601529190041660c0830152600501549182169281019290925261ffff600160401b82041661010083015260ff600160501b9091041661012082015294509492505050565b5f80603c8302613c728686614429565b0142101595945050505050565b60a08401515f906001600160a01b031615613d2757816101a0015115613cd857613cb58560c001516001600160601b031661443e565b9050613cd388866060015187608001516001600160601b0316614097565b613df5565b6002613cf086608001516001600160601b031661443e565b901c9050613cd3888660a00151836003613d0a9190615d0c565b8860c001516001600160601b0316613d229190615a58565b614097565b816101a0015115613d4b57604051639d49773160e01b815260040160405180910390fd5b613d6185608001516001600160601b031661443e565b90508160c001516001600160601b03165f14613df5576001860180546001600160a01b031690556020830151613d98908390614460565b15613df557336001600160a01b031682608001516001600160a01b031603613dd95760c0820151613dd2906001600160601b031682615a58565b9050613df5565b613df58883608001518460c001516001600160601b0316614097565b8160200151602001516001600160601b0316811115613e3157613e2c88338460200151602001516001600160601b03168403614097565b613e69565b8160200151602001516001600160601b0316811015613e6957613e69888833848660200151602001516001600160601b031603613ebf565b60208083015101516001600160601b031660808601525f60a0860152336060860152825161ffff166101008601526101a0820151612969576020808501519086015260a082015160408601525050505050505050565b6001600160a01b0382165f908152600685016020526040902054818110613f3d576001600160a01b0383165f818152600687016020526040908190208484039055517f85f32beeaff2d0019a8d196f06790c9a652191759c46643311344fd38920423c90613f309085815260200190565b60405180910390a2610a41565b613f468461431f565b6040516323b872dd60e01b81526001600160a01b0385811660048301523060248301526044820185905291909116906323b872dd906064016020604051808303815f875af1158015613f9a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061296d9190615a6b565b6001600160401b0382165f90815260028501602090815260408083206001845290915281205482900361402557506002830154600190600160c01b900463ffffffff168110614020576040516367a1907f60e01b815260040160405180910390fd5b612fa4565b5060028301546001600160401b03165f908152600185016020908152604080832084845290915290205463ffffffff1680158015906140795750600284015463ffffffff600160c01b909104811690821610155b15612fa4576040516367a1907f60e01b815260040160405180910390fd5b6001600160a01b0382165f908152600684016020526040812080548392906140c0908490615a58565b90915550506040518181526001600160a01b038316907f6de6fe586196fa05b73b973026c5fda3968a2933989bff3a0b6bd57644fab6069060200160405180910390a2505050565b5f54610100900460ff1661412e5760405162461bcd60e51b81526004016107a790615d23565b6141366144d0565b6141546001600160a01b0382161561414e5781613064565b33613064565b5060c9805461ff001916610100179055565b5f54610100900460ff1661418c5760405162461bcd60e51b81526004016107a790615d23565b6001600160401b034611156141b45760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381163b6142435760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016107a7565b5f80516020615dd683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61427a836144f6565b5f825111806142865750805b1561092d576129708383614535565b6142a960c954610100900460ff1660021490565b6142c65760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001612bde565b604051635437cecf60e11b81526a3a30b4b5b7afba37b5b2b760a91b60048201525f60248201819052906001600160a01b0383169063a86f9d9e90604401602060405180830381865afa158015614378573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610db691906157f1565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f805f6143fa858561455a565b91509150612e5e8161459c565b610c4382825a6146e5565b5f617e2c8210158015610db6575050617e90101590565b5f8183116144375781610b1e565b5090919050565b5f8115614459576003614452836007615d0c565b901c610db6565b5f92915050565b5f826101800151801561447e575082610120015163ffffffff166001145b80610b1e57508261016001518015614497575081516020145b8015610b1e57507f20d34d7a20a139f9be221ba2163925c0c86ed02d34033f288f010d23a63ef4b76144c883615d6e565b149392505050565b5f54610100900460ff16610ec85760405162461bcd60e51b81526004016107a790615d23565b6144ff816141d6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b1e8383604051806060016040528060278152602001615df660279139614728565b5f80825160410361458e576020830151604084015160608501515f1a6145828782858561479c565b94509450505050614595565b505f905060025b9250929050565b5f8160048111156145af576145af615d94565b036145b75750565b60018160048111156145cb576145cb615d94565b036146185760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016107a7565b600281600481111561462c5761462c615d94565b036146795760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016107a7565b600381600481111561468d5761468d615d94565b03610b0c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016107a7565b815f036146f157505050565b61470b83838360405180602001604052805f815250614856565b61092d57604051634c67134d60e11b815260040160405180910390fd5b60605f80856001600160a01b0316856040516147449190615da8565b5f60405180830381855af49150503d805f811461477c576040519150601f19603f3d011682016040523d82523d5f602084013e614781565b606091505b509150915061479286838387614893565b9695505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156147d157505f9050600361136d565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614822573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661484a575f6001925092505061136d565b965f9650945050505050565b5f6001600160a01b03851661487e57604051634c67134d60e11b815260040160405180910390fd5b5f80835160208501878988f195945050505050565b606083156149015782515f036148fa576001600160a01b0385163b6148fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107a7565b5081612fa4565b612fa483838151156149165781518083602001fd5b8060405162461bcd60e51b81526004016107a79190615dc3565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080516101c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b604051806101c00160405280614a45614983565b81526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101609091015290565b604051806101a00160405280614b17614983565b81525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082018190526101208201819052610140820181905261016082018190526101809091015290565b6040518060600160405280614b88614983565b81526040805160c0810182525f808252602080830182905282840182905260608084018390526080840181905260a084015284019190915291015290565b80356001600160401b0381168114614bdc575f80fd5b919050565b5f8083601f840112614bf1575f80fd5b5081356001600160401b03811115614c07575f80fd5b602083019150836020828501011115614595575f80fd5b5f805f60408486031215614c30575f80fd5b614c3984614bc6565b925060208401356001600160401b03811115614c53575f80fd5b614c5f86828701614be1565b9497909650939450505050565b6001600160a01b0381168114610b0c575f80fd5b8035614bdc81614c6c565b8015158114610b0c575f80fd5b8035614bdc81614c8b565b5f805f8060808587031215614cb6575f80fd5b8435614cc181614c6c565b93506020850135614cd181614c6c565b9250604085013591506060850135614ce881614c8b565b939692955090935050565b5f60208284031215614d03575f80fd5b8135610b1e81614c6c565b5f805f60608486031215614d20575f80fd5b614d2984614bc6565b9250602084013591506040840135614d4081614c8b565b809150509250925092565b5f60208284031215614d5b575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715614d9857614d98614d62565b60405290565b6040516101c081016001600160401b0381118282101715614d9857614d98614d62565b60405160c081016001600160401b0381118282101715614d9857614d98614d62565b604051601f8201601f191681016001600160401b0381118282101715614e0b57614e0b614d62565b604052919050565b5f82601f830112614e22575f80fd5b81356001600160401b03811115614e3b57614e3b614d62565b614e4e601f8201601f1916602001614de3565b818152846020838601011115614e62575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614e8f575f80fd5b8235614e9a81614c6c565b915060208301356001600160401b03811115614eb4575f80fd5b614ec085828601614e13565b9150509250929050565b803563ffffffff81168114614bdc575f80fd5b5f8060408385031215614eee575f80fd5b614ef783614bc6565b9150614f0560208401614eca565b90509250929050565b5f610140820190508251825260208301516020830152604083015160408301526060830151614f4860608401826001600160a01b03169052565b506080830151614f6360808401826001600160601b03169052565b5060a0830151614f7e60a08401826001600160a01b03169052565b5060c0830151614f9960c08401826001600160601b03169052565b5060e0830151614fb460e08401826001600160401b03169052565b506101008381015161ffff16908301526101209283015160ff16929091019190915290565b5f60208284031215614fe9575f80fd5b610b1e82614bc6565b815181526020808301516001600160a01b0316908201526040808301516001600160601b0316908201526060808301516001600160401b039081169183019190915260808084015182169083015260a080840151918216908301526101008201905060c083015161506b60c084018263ffffffff169052565b5060e083015161508360e084018263ffffffff169052565b5092915050565b5f806040838503121561509b575f80fd5b8235915060208301356150ad81614c8b565b809150509250929050565b6001600160401b0380825116835280602083015116602084015260408201511515604084015260ff606083015116606084015261ffff608083015116608084015263ffffffff60a08301511660a08401528060c08301511660c0840152505050565b838152610180810161515d602083018580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b612fa460a08301846150b8565b5f610100820190506001600160401b038084511683528060208501511660208401528060408501511660408401528060608501511660608401525063ffffffff608084015116608083015260a08301516151cf60a08401826001600160601b03169052565b5060c08301516151e460c084018260ff169052565b5060e083015161508360e084018215159052565b6101608101615235828580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b610b1e60808301846150b8565b5f805f8060408587031215615255575f80fd5b84356001600160401b038082111561526b575f80fd5b61527788838901614be1565b9096509450602087013591508082111561528f575f80fd5b5061529c87828801614be1565b95989497509550505050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a08101516152ee60a08401826001600160a01b03169052565b5060c081015161530960c08401826001600160401b03169052565b5060e081015161532160e084018263ffffffff169052565b50610100818101516001600160401b039081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015115159083015261018080820151908301526101a0808201516001600160a01b03811682850152612970565b5f815180845260208085019450602084015f5b838110156153ea57815180516001600160a01b03168852838101516001600160601b0316848901526040908101516001600160401b0316908801526060909601959082019060010161539d565b509495945050505050565b5f6101e061540383866152a8565b806101c08401526154168184018561538a565b95945050505050565b5f8060408385031215615430575f80fd5b61543983614bc6565b946020939093013593505050565b5f60208284031215615457575f80fd5b8135610b1e81614c8b565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b5f60e08201905082546001600160401b038082168452808260401c1660208501525060ff8160801c161515604084015260ff8160881c16606084015261ffff8160901c16608084015263ffffffff8160a01c1660a08401528060c01c60c08401525092915050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b61ffff81168114610b0c575f80fd5b8035614bdc816155b0565b5f608082840312156155da575f80fd5b604051608081018181106001600160401b03821117156155fc576155fc614d62565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b5f6040828403121561563d575f80fd5b615645614d76565b90508135615652816155b0565b815260208201356001600160401b0381111561566c575f80fd5b61567884828501614e13565b60208301525092915050565b5f805f838503610260811215615698575f80fd5b6101c0808212156156a7575f80fd5b6156af614d9e565b915085358252602086013560208301526040860135604083015260608601356060830152608086013560808301526156e960a08701614c80565b60a08301526156fa60c08701614bc6565b60c083015261570b60e08701614eca565b60e083015261010061571e818801614bc6565b90830152610120615730878201614bc6565b908301526101406157428782016155bf565b90830152610160615754878201614c98565b9083015261018086810135908301526101a0615771818801614c80565b8184015250819450615785878288016155ca565b935050506102408401356001600160401b038111156157a2575f80fd5b6157ae8682870161562d565b9150509250925092565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b03808416806157e5576157e56157b8565b92169190910692915050565b5f60208284031215615801575f80fd5b8151610b1e81614c6c565b80516001600160601b0381168114614bdc575f80fd5b5f60c08284031215615832575f80fd5b61583a614dc1565b8251815261584a6020840161580c565b602082015261585b6040840161580c565b6040820152606083015162ffffff81168114615875575f80fd5b60608201526080830151615888816155b0565b608082015260a083015160ff811681146158a0575f80fd5b60a08201529392505050565b5f5b838110156158c65781810151838201526020016158ae565b50505f910152565b5f81518084526158e58160208601602086016158ac565b601f01601f19169290920160200192915050565b61ffff81511682525f602082015160406020850152612fa460408501826158ce565b83518152602080850151818301526040808601516001600160a01b03908116828501526060808801516001600160401b03168186015260808089015115159086015260a08089015115159086015260c08089015190921691850191909152855160e0850152918501516101008401528401516101208301528301516101408201525f61018080610160840152614792818401856158f9565b845181526020808601519082015260408086015190820152606094850151948101949094526001600160a01b039290921660808401526001600160601b031660a083015261ffff1660c082015260e00190565b634e487b7160e01b5f52600160045260245ffd5b5f82615a2857615a286157b8565b500690565b5f60208284031215615a3d575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610db657610db6615a44565b5f60208284031215615a7b575f80fd5b8151610b1e81614c8b565b81810381811115610db657610db6615a44565b5f82601f830112615aa8575f80fd5b813560206001600160401b0380831115615ac457615ac4614d62565b8260051b615ad3838201614de3565b9384528581018301938381019088861115615aec575f80fd5b84880192505b85831015615b6957823584811115615b08575f80fd5b88016040818b03601f1901811315615b1e575f80fd5b615b26614d76565b87830135615b3381614c6c565b8152908201359086821115615b46575f80fd5b615b548c8984860101614e13565b81890152845250509184019190840190615af2565b98975050505050505050565b5f60208284031215615b85575f80fd5b81356001600160401b0380821115615b9b575f80fd5b9083019060c08286031215615bae575f80fd5b615bb6614dc1565b615bbf83614c80565b8152615bcd60208401614c80565b60208201526040830135604082015260608301356060820152608083013582811115615bf7575f80fd5b615c0387828601615a99565b60808301525060a083013582811115615c1a575f80fd5b615c2687828601614e13565b60a08301525095945050505050565b6001600160401b0381811683821601908082111561508357615083615a44565b6001600160401b0382811682821603908082111561508357615083615a44565b818382375f9101908152919050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60208284031215615cc2575f80fd5b8151610b1e816155b0565b5f6102006001600160601b0386168352615cea60208401866152a8565b806101e08401526147928184018561538a565b6101c08101610db682846152a8565b8082028115828204841417610db657610db6615a44565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b80516020808301519190811015615d8e575f198160200360031b1b821691505b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f8251615db98184602087016158ac565b9190910192915050565b602081525f610b1e60208301846158ce56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220db2a18e7a705df631f0e11429aeb2220aa6c2c995a693e956c7178e18898c5c764736f6c63430008180033
Deployed Bytecode
0x6080604052600436106101ff575f3560e01c806379ba509711610113578063c3daab961161009d578063e30c39781161006d578063e30c3978146106b4578063ef16e845146106d1578063f2fde38b146106f2578063fd257e2914610711578063ff00c39114610730575f80fd5b8063c3daab9614610615578063c3f909d414610634578063dde89cf514610655578063e07baba614610677575f80fd5b80638da5cb5b116100e35780638da5cb5b146104c65780639413caa9146104e3578063a86f9d9e146104f7578063a9c2c83514610516578063c19d93fb14610535575f80fd5b806379ba50971461046b5780638456cb591461047f5780638778209d146104935780638abf6077146104b2575f80fd5b80633f4ba83a11610194578063563479a511610164578063563479a5146103c05780635c975abb146103ec5780635fa15e791461040c5780636074b8c114610438578063715018a614610457575f80fd5b80633f4ba83a146103585780634dcb05f91461036c5780634f1ef2861461038b57806352d1902d1461039e575f80fd5b80633075db56116101cf5780633075db56146102bf5780633659cfe6146102e35780633ab76e9f146103025780633eb6b8cf14610339575f80fd5b8063069489a21461022f57806310d008bd1461024357806326af79861461026257806329d1b62f146102a0575f80fd5b3661022b5761020c61074f565b61022957604051630d28633960e01b815260040160405180910390fd5b005b5f80fd5b34801561023a575f80fd5b50610229610763565b34801561024e575f80fd5b5061022961025d366004614c1e565b61081a565b34801561026d575f80fd5b50610276610932565b604080516001600160401b0390941684526020840192909252908201526060015b60405180910390f35b3480156102ab575f80fd5b506102296102ba366004614ca3565b610965565b3480156102ca575f80fd5b506102d361074f565b6040519015158152602001610297565b3480156102ee575f80fd5b506102296102fd366004614cf3565b610a48565b34801561030d575f80fd5b50609754610321906001600160a01b031681565b6040516001600160a01b039091168152602001610297565b348015610344575f80fd5b50610321610353366004614d0e565b610b0f565b348015610363575f80fd5b50610229610b25565b348015610377575f80fd5b50610229610386366004614d4b565b610b50565b610229610399366004614e7e565b610b8e565b3480156103a9575f80fd5b506103b2610c47565b604051908152602001610297565b3480156103cb575f80fd5b506103df6103da366004614edd565b610cf8565b6040516102979190614f0e565b3480156103f7575f80fd5b506102d360c954610100900460ff1660021490565b348015610417575f80fd5b5061042b610426366004614fd9565b610dbc565b6040516102979190614ff2565b348015610443575f80fd5b50610321610452366004614fd9565b610ea3565b348015610462575f80fd5b50610229610eb7565b348015610476575f80fd5b50610229610eca565b34801561048a575f80fd5b50610229610f41565b34801561049e575f80fd5b506102296104ad366004614fd9565b610f54565b3480156104bd575f80fd5b5061032161103f565b3480156104d1575f80fd5b506033546001600160a01b0316610321565b3480156104ee575f80fd5b5061027661104d565b348015610502575f80fd5b5061032161051136600461508a565b61106f565b348015610521575f80fd5b506103b2610530366004614cf3565b61107b565b348015610540575f80fd5b5060fe54604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c0830152610606929183565b6040516102979392919061511a565b348015610620575f80fd5b5061022961062f366004614d4b565b611099565b34801561063f575f80fd5b506106486110d7565b604051610297919061516a565b348015610660575f80fd5b5061066961116e565b6040516102979291906151f8565b348015610682575f80fd5b5060c95461069c906201000090046001600160401b031681565b6040516001600160401b039091168152602001610297565b3480156106bf575f80fd5b506065546001600160a01b0316610321565b6106e46106df366004615242565b611258565b6040516102979291906153f5565b3480156106fd575f80fd5b5061022961070c366004614cf3565b611376565b34801561071c575f80fd5b506103df61072b36600461541f565b6113e7565b34801561073b575f80fd5b5061022961074a366004615447565b611403565b5f600261075a611418565b60ff1614905090565b61076b611457565b5f54600290610100900460ff1615801561078b57505f5460ff8083169116105b6107b05760405162461bcd60e51b81526004016107a790615462565b60405180910390fd5b5f8054610100805466ffffffffffffff60881b1916815560fe83905561ff001960ff851661ffff199093168317909117169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b61082e60c954610100900460ff1660021490565b1561084c5760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610878576040516333018e5560e11b815260040160405180910390fd5b6002610882611418565b60ff16036108a35760405163dfc60d8560e01b815260040160405180910390fd5b6108ad60026114b1565b5f6108b66110d7565b90506108c760fb82308787876114f9565b6108d281855f612078565b156108e8576108e860fb823084606001516120e7565b506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b9061091b90610100906154b0565b60405180910390a161092d60016114b1565b505050565b61010054600160401b90046001600160401b03165f8061095b60fb6109556110d7565b85612976565b9394909392509050565b5f54610100900460ff161580801561098357505f54600160ff909116105b8061099c5750303b15801561099c57505f5460ff166001145b6109b85760405162461bcd60e51b81526004016107a790615462565b5f805460ff1916600117905580156109d9575f805461ff0019166101001790555b6109e385856129ef565b6109ee60fb84612a29565b81156109fc576109fc612b71565b8015610a41575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b037f000000000000000000000000fee0b488da4dfc7cd784d47de42b9467c1fae0f3163003610a905760405162461bcd60e51b81526004016107a790615518565b7f000000000000000000000000fee0b488da4dfc7cd784d47de42b9467c1fae0f36001600160a01b0316610ac2612be8565b6001600160a01b031614610ae85760405162461bcd60e51b81526004016107a790615564565b610af181612c03565b604080515f80825260208201909252610b0c91839190612c0b565b50565b5f610b1b848484612d75565b90505b9392505050565b610b2d612e66565b61010080546001600160c01b0316600160c01b426001600160401b031602179055565b610b6460c954610100900460ff1660021490565b15610b825760405163bae6e2a960e01b815260040160405180910390fd5b610b0c60fb3083612e78565b6001600160a01b037f000000000000000000000000fee0b488da4dfc7cd784d47de42b9467c1fae0f3163003610bd65760405162461bcd60e51b81526004016107a790615518565b7f000000000000000000000000fee0b488da4dfc7cd784d47de42b9467c1fae0f36001600160a01b0316610c08612be8565b6001600160a01b031614610c2e5760405162461bcd60e51b81526004016107a790615564565b610c3782612c03565b610c4382826001612c0b565b5050565b5f306001600160a01b037f000000000000000000000000fee0b488da4dfc7cd784d47de42b9467c1fae0f31614610ce65760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016107a7565b505f80516020615dd683398151915290565b610d00614930565b610d1460fb610d0d6110d7565b8585612f1e565b6040805161014081018252825481526001830154602082015260028301549181019190915260038201546001600160a01b0380821660608401526001600160601b03600160a01b9283900481166080850152600485015491821660a08501529190041660c08201526005909101546001600160401b03811660e083015261ffff600160401b82041661010083015260ff600160501b9091041661012082015290505b92915050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152610e0f60fb610e096110d7565b84612fac565b5060408051610100810182528254815260018301546001600160a01b03811660208301526001600160601b03600160a01b90910416918101919091526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b82041660a083015263ffffffff600160c01b8204811660c0840152600160e01b9091041660e082015292915050565b5f610db660fb610eb16110d7565b8461300c565b610ebf611457565b610ec85f613064565b565b60655433906001600160a01b03168114610f385760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016107a7565b610b0c81613064565b610f49612b71565b610ec833600161307d565b610f6860c954610100900460ff1660021490565b15610f865760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610fb2576040516333018e5560e11b815260040160405180910390fd5b6002610fbc611418565b60ff1603610fdd5760405163dfc60d8560e01b815260040160405180910390fd5b610fe760026114b1565b610ffb60fb610ff46110d7565b30846120e7565b6040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b9061102d90610100906154b0565b60405180910390a1610b0c60016114b1565b5f611048612be8565b905090565b60ff54600160801b90046001600160401b03165f8061095b60fb6109556110d7565b5f610b1e468484612d75565b6001600160a01b0381165f9081526101016020526040812054610db6565b6110ad60c954610100900460ff1660021490565b156110cb5760405163bae6e2a960e01b815260040160405180910390fd5b610b0c60fb30836130fc565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915250604080516101008101825262028c6181526204f1a060208201526204f3a091810191909152601060608201819052630e4e1c0060808301526806c6b935b8bbd4000060a083015260c0820152600160e082015290565b604080516080810182525f808252602082018190529181018290526060810191909152611199614983565b5050604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015291565b6112606149be565b606061127660c954610100900460ff1660021490565b156112945760405163bae6e2a960e01b815260040160405180910390fd5b600261129e611418565b60ff16036112bf5760405163dfc60d8560e01b815260040160405180910390fd5b6112c960026114b1565b5f6112d26110d7565b90506112e460fb82308a8a8a8a613160565b60c082015191945092506112fb9082906001612078565b8015611312575061010054600160801b900460ff16155b156113285761132860fb823084606001516120e7565b506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b9061135b90610100906154b0565b60405180910390a161136d60016114b1565b94509492505050565b61137e611457565b606580546001600160a01b0383166001600160a01b031990911681179091556113af6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6113ef614930565b610d1460fb6113fc6110d7565b85856138fe565b61140d338261307d565b610b0c60fb8261397b565b5f61142246613a28565b1561144d57507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b6033546001600160a01b03163314610ec85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016107a7565b6114ba46613a28565b156114e557807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b5f808061150884860186615684565b9250925092508260c001516001600160401b0316866001600160401b03161461154457604051638a1c400f60e01b815260040160405180910390fd5b8151158061155457506020820151155b8061156157506040820151155b1561157f576040516317eddea160e11b815260040160405180910390fd5b611587614a31565b6040805160e08101825260058c01546001600160401b038082168352600160401b820481166020840190815260ff600160801b84048116151595850195909552600160881b8304909416606084015261ffff600160901b830416608084015263ffffffff600160a01b83041660a0840152600160c01b909104811660c0808401919091529184529151908601519082169116111580611639575080515160c08501516001600160401b03918216911610155b1561165757604051638a1c400f60e01b815260040160405180910390fd5b88604001518460c0015161166b91906157cc565b6001600160401b0390811660e083018190525f90815260208c9052604090206002810154909116610100830181905260c08b01516116ae9160ff90911690613a55565b156116be57604084015160a08301525b60018101546001600160a01b0316608083018190526116ec576101a08501516001600160a01b031660808301525b6001810154600160a01b90046001600160601b031660c083810191909152815460608401528501516101008301516001600160401b039182169116141580611740575061173885613a82565b826060015114155b1561175e57604051632ec3485560e11b815260040160405180910390fd5b611766614930565b6117728c838786613ab1565b63ffffffff909116610120850152845190915061ffff1615806117a4575085610140015161ffff16845f015161ffff16105b806117be575080610100015161ffff16845f015161ffff16105b156117dc57604051631a32f51360e01b815260040160405180910390fd5b604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015611835573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185991906157f1565b610100850151604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa1580156118b0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118d491906157f1565b865160405163576c3de760e01b815261ffff90911660048201529091506001600160a01b0382169063576c3de79060240160c060405180830381865afa158015611920573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119449190615822565b602086015261014088015160405163576c3de760e01b815261ffff90911660048201526001600160a01b0382169063576c3de79060240160c060405180830381865afa158015611996573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ba9190615822565b856040018190525050506119f88160e001516001600160401b0316845f015160c001516001600160401b031685604001516080015161ffff16613c62565b156101808401526020830151604001516001600160601b031615801590611a2a575060a08101516001600160a01b0316155b8015611a41575082610120015163ffffffff166001145b8015611a54575061010081015161ffff16155b8015611a6257508261018001515b15611a9d5782608001516001600160a01b0316336001600160a01b031614611a9d57604051632185a2ad60e21b815260040160405180910390fd5b60208301515115611c0757602083015151604051635437cecf60e11b815260048101919091525f60248201819052906001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015611afb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b1f91906157f1565b90505f82610100015161ffff16865f015161ffff16148015611b5157506020850151604001516001600160601b031615155b6040805160e08101825260608089015182528b8301516020830152338284018190526101008a01516001600160401b03169183019190915283151560808301526101608c0151151560a083015260c0820152905163043d132d60e31b8152919250906001600160a01b038416906321e8996890611bd69084908c908c9060040161591b565b5f604051808303815f87803b158015611bed575f80fd5b505af1158015611bff573d5f803e3d5ffd5b505050505050505b602080840151604001516001600160601b0316156101608501528181015190860151148015611c3d575080604001518360a00151145b15156101a0840152610100810151845161ffff91821691161115611cc657611c6a8c8b8484898989613c7f565b8261010001516001600160401b03167fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f8633866020015160200151885f0151604051611cb994939291906159b3565b60405180910390a2611ebf565b826101a0015115611cea57604051639d49773160e01b815260040160405180910390fd5b82610160015115611dab5760208084015101516001600160601b031615611d1357611d13615a06565b60808101516001600160601b0316158015611d39575060a08101516001600160a01b0316155b611d4557611d45615a06565b33606082018190526020808701519083015260a0840151604080840191909152610100850151865191516001600160401b03909116927fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f92611cb9928a92915f916159b3565b60a08101516001600160a01b031615611dd7576040516382ef169960e01b815260040160405180910390fd5b611e0c8160e001516001600160401b0316845f015160c001516001600160401b031685602001516060015162ffffff16613c62565b15611e2a5760405163378b1eff60e21b815260040160405180910390fd5b611e478c8b338660200151604001516001600160601b0316613ebf565b6020830180516040908101516001600160601b031660c08401523360a084018190526101008601519251820151875192516001600160401b03909416937fb4c0a86c1ff239277697775b1e91d3375fd3a5ef6b345aa4e2f6001c890558f693611eb6938b9390929091906159b3565b60405180910390a25b428160e001906001600160401b031690816001600160401b031681525050808c6002015f8560e001516001600160401b03166001600160401b031681526020019081526020015f205f85610120015163ffffffff1663ffffffff1681526020019081526020015f205f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060808201518160030160146101000a8154816001600160601b0302191690836001600160601b0316021790555060a0820151816004015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060c08201518160040160146101000a8154816001600160601b0302191690836001600160601b0316021790555060e0820151816005015f6101000a8154816001600160401b0302191690836001600160401b031602179055506101008201518160050160086101000a81548161ffff021916908361ffff16021790555061012082015181600501600a6101000a81548160ff021916908360ff160217905550905050505050505050505050505050565b5f83606001516001600160401b03165f0361209457505f610b1e565b6060840151677fffffffffffffff600191821c169081116120b9576001915050610b1e565b826120c857600181901c6120ca565b5f5b6120dd826001600160401b038716615a1a565b1495945050505050565b6001600160401b03811615612970576120fe614b03565b6040805160e08101825260058701546001600160401b038082168352600160401b82048116602080850191825260ff600160801b85048116151586880152600160881b850416606086015261ffff600160901b850416608086015263ffffffff600160a01b85041660a0860152600160c01b909304821660c0850152928552915190911690830181905290850151612195916157cc565b6001600160401b0390811660408084018290525f9182526020888152912090830151600282015491929182169116146121e157604051632ec3485560e11b815260040160405180910390fd5b6002810154600160e01b900463ffffffff1660a08301819052608083018190525f036122205760405163d4345b9760e01b815260040160405180910390fd5b6040808301516001600160401b039081165f908152600289016020908152838220608087015163ffffffff168352815292902060019081015460e086015291840180519092011690525b81515160208301516001600160401b0391821691161080156122a15750826001600160401b031682606001516001600160401b0316105b156126b05784604001516001600160401b031682602001516001600160401b0316816122cf576122cf6157b8565b066001600160401b0390811660408481018290525f91825260208981529120908401516002820154919350821691161461231c57604051632ec3485560e11b815260040160405180910390fd5b612330868284604001518560e00151613fbe565b63ffffffff1660808301819052156126b0576040828101516001600160401b03165f908152600288016020908152828220608086015163ffffffff1683529052206005810154600160401b900461ffff1660c084015260048101546001600160a01b03161561239f57506126b0565b6101808301516001600160a01b031661243c57604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201526001600160a01b0386169063a86f9d9e90604401602060405180830381865afa158015612408573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061242c91906157f1565b6001600160a01b03166101808401525b6101808301516020840151604051635c42d07960e01b81526001600160401b0390911660048201525f916001600160a01b031690635c42d07990602401602060405180830381865afa158015612494573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124b891906157f1565b60c085015160405163576c3de760e01b815261ffff90911660048201526001600160a01b03919091169063576c3de79060240160c060405180830381865afa158015612506573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061252a9190615822565b606001516005830154855160c00151919250612558916001600160401b03918216911662ffffff8416613c62565b6125635750506126b0565b50608083015163ffffffff1660a0840152600181015460e084015260038101546001600160a01b03811661016085018190526125b191899190600160a01b90046001600160601b0316614097565b8261016001516001600160a01b031683602001516001600160401b03167fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2898560e001515f8760c0015160405161261e93929190928352602083019190915261ffff16604082015260600190565b60405180910390a36126448660c0015160ff1684602001516001600160401b0316613a55565b15612684576002810154801561268257610100840181905260208401516001600160401b0316610120850152608084015163ffffffff166101408501525b505b506020820180516001600160401b0360019182018116909252606084018051909101909116905261226a565b60608201516001600160401b03161561296d57606082015182516020015160408701519101906001600160401b03908116908216816126f1576126f16157b8565b6001600160401b039190068116604080860182905260058a018054938516600160401b026fffffffffffffffff0000000000000000199094169390931790925560a08501515f91825260208a9052919020600201805463ffffffff909216600160e01b026001600160e01b039092169190911790556101008301511561296b576101208301516004880180546fffffffffffffffffffffffffffffffff16600160801b6001600160401b039384169081026001600160c01b031691909117600160c01b4285160217909155908216146128375785604001516001600160401b03168361012001516001600160401b0316816127ee576127ee6157b8565b066001600160401b031660408481018290526101408501515f92835260208a9052912060020180546001600160e01b0316600160e01b63ffffffff909316929092029190911790555b604051635437cecf60e11b81526d7369676e616c5f7365727669636560901b60048201525f60248201526001600160a01b0386169063a86f9d9e90604401602060405180830381865afa158015612890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128b491906157f1565b86516101208501516101008601516040516313e4299d60e21b81526001600160401b0393841660048201527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da169602482015292909116604483015260648201526001600160a01b039190911690634f90a674906084016020604051808303815f875af1158015612945573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129699190615a2d565b505b505b50505b50505050565b5f805f80612985878787612fac565b60028201549193509150600160e01b900463ffffffff16156129e5576001600160401b0381165f90815260028881016020908152604080842086840154600160e01b900463ffffffff168552909152909120600181015491015490945092505b5050935093915050565b806001600160a01b038116612a175760405163538ba4f960e01b815260040160405180910390fd5b612a2083614108565b61092d82614166565b5f819003612a4a5760405163d6d0f75560e01b815260040160405180910390fd5b600482018054426001600160401b03908116600160401b81026001600160801b031990931643929092169190911782179092556005808501805467ffffffffffffffff1990811660019081179092555f80805260208881526040808320600280820180546001600160e01b037fffffffff00000000ffffffffffffffff0000000000000000ffffffffffffffff909116909a17600160c11b1799909916600160e01b17909855858155968a01825280832085845282528083209485018990556003850180546001600160a01b031916905594840180549093169096179091558251868152948501819052918401829052919281907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a350505050565b612b8560c954610100900460ff1660021490565b15612ba35760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b5f80516020615dd6833981519152546001600160a01b031690565b610b0c611457565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612c3e5761092d836141d6565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612c98575060408051601f3d908101601f19168201909252612c9591810190615a2d565b60015b612cfb5760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016107a7565b5f80516020615dd68339815191528114612d695760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016107a7565b5061092d838383614271565b6097545f906001600160a01b031680612da157604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0386166004820152602481018590526001600160a01b038216906328f713cc90604401602060405180830381865afa158015612df3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e1791906157f1565b915082158015612e2e57506001600160a01b038216155b15612e5e57604051632b0d65db60e01b81526001600160401b0386166004820152602481018590526044016107a7565b509392505050565b612e6e614295565b610ec8335f61307d565b335f90815260068401602052604081208054839290612e98908490615a58565b90915550612ea790508261431f565b6040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b0391909116906323b872dd906064015b6020604051808303815f875af1158015612efa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129709190615a6b565b5f805f612f2c878787612fac565b915091508363ffffffff165f1480612f595750600282015463ffffffff600160c01b909104811690851610155b15612f775760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b03165f908152600287016020908152604080832063ffffffff8716845290915290209150505b949350505050565b5f80836040015183612fbe91906157cc565b6001600160401b038181165f908152602088905260409020600281015490945091925084811691161461300457604051638a1c400f60e01b815260040160405180910390fd5b935093915050565b5f80613019858585612fac565b506002810154909150600160e01b900463ffffffff165f819003613041575f92505050610b1e565b61304d86868684612f1e565b600301546001600160a01b03169695505050505050565b606580546001600160a01b0319169055610b0c8161439c565b6d636861696e5f7761746368646f6760901b6130a16033546001600160a01b031690565b6001600160a01b0316336001600160a01b0316141580156130de57506130c881600161106f565b6001600160a01b0316336001600160a01b031614155b1561092d57604051630d85cccf60e11b815260040160405180910390fd5b335f9081526006840160205260408120805483929061311c908490615a86565b9091555061312b90508261431f565b60405163a9059cbb60e01b8152336004820152602481018390526001600160a01b03919091169063a9059cbb90604401612ede565b6131686149be565b6060613172614b75565b61317e86880188615b75565b602080830182905201516001600160a01b03166131a057602080820151339101525b6040805160e08101825260058c01546001600160401b038082168352600160401b82048116602080850191825260ff600160801b85048116151596860196909652600160881b8404909516606085015261ffff600160901b840416608085015263ffffffff600160a01b84041660a0850152600160c01b9092041660c0830152908352908a015190516132339190615c35565b61323e906001615c35565b8151516001600160401b0391821691161061326c576040516351ec7d5360e01b815260040160405180910390fd5b60408901518151518b915f9161328490600190615c55565b61328e91906157cc565b6001600160401b0316815260208082019290925260409081015f20549083015281015160600151158015906132cf5750806020015160600151816040015114155b156132ed57604051630d41ec8760e11b815260040160405180910390fd5b604080516101c0810182525f194301804082525f6020808401829052838501829052858101805186015160608601527f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd6080808701919091529051909101516001600160a01b031660a08501528551516001600160401b0390811660c0860152908e015163ffffffff1660e08501524281166101008501529091166101208301526101408201528515610160820181905291830151610180820152336101a082015293501561340a576133bf46613a28565b6133dc5760405163df9969ef60e01b815260040160405180910390fd5b5f804960408501819052900361340557604051639e7e2ddd60e01b815260040160405180910390fd5b6134c7565b848460405161341a929190615c75565b60408051918290039091209084015260e089015180156134615750336001600160a01b03166134558460400151836020015160a001516143ed565b6001600160a01b031614155b1561347f5760405163f6ee3bdb60e01b815260040160405180910390fd5b8260c001516001600160401b03167fa07bc5e8f00f6065c8727821591c519efd2348e4ff0c26560a85592e85b6f41886866040516134be929190615c84565b60405180910390a25b8051516040805144602082015260c09290921b6001600160c01b0319169082015243604882015260680160408051808303601f1901815291815281516020928301209185019190915251635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b038a169063a86f9d9e90604401602060405180830381865afa158015613567573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061358b91906157f1565b825151604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa1580156135df573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061360391906157f1565b6101a086015160208701516040516352c5c56b60e01b81526001600160a01b03928316600482015260248101919091529192508216906352c5c56b90604401602060405180830381865afa15801561365d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136819190615cb2565b61ffff1661014086015250506040805161010081019091525f90806136a586613a82565b81525f6020820181905260a0808e01516001600160601b03166040808501919091528651516001600160401b0390811660608601526101008a015181166080860152431691840191909152600160c084015260e0909201819052908c015184515192935083928e9291613717916157cc565b6001600160401b03908116825260208083019390935260409182015f208451815592840151918401516001600160a01b03909216600160a01b6001600160601b039384160217600180850191909155606085015160029094018054608087015160a08089015160c08a015160e0909a01519887166001600160801b031990941693909317600160401b92871692909202919091176bffffffffffffffffffffffff60801b1916600160801b9286169290920263ffffffff60c01b191691909117600160c01b63ffffffff98891602176001600160e01b0316600160e01b97909616969096029490941790935560058f01805467ffffffffffffffff19811690831690940190911692909217909155908b0151613839918d918c91339116613ebf565b341580159061384757504115155b15613856576138564134614407565b604080515f8082526020820190925290613896565b604080516060810182525f80825260208083018290529282015282525f1990920191018161386b5790505b509250336001600160a01b03168460c001516001600160401b03167fcda4e564245eb15494bc6da29f6a42e1941cf57f5314bf35bab8a1fca0a9c60a8c60a0015187876040516138e893929190615ccd565b60405180910390a3505097509795505050505050565b5f805f61390c878787612fac565b915091505f61391d88848488613fbe565b90508063ffffffff165f036139455760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b039091165f908152600288016020908152604080832063ffffffff909416835292905220915050949350505050565b6005820154811515600160801b90910460ff161515036139ae5760405163689d009d60e11b815260040160405180910390fd5b60058201805460ff60801b1916600160801b83151502179055806139ef576005820180546001600160c01b0316600160c01b426001600160401b0316021790555b60405181151581527fed64db85835d07c3c990b8ebdd55e32d64e5ed53143b6ef2179e7bfaf17ddc3b9060200160405180910390a15050565b5f6001821480613a39575061426882145b80613a46575062aa36a782145b80610db65750610db682614412565b5f60018311613a6657506001610db6565b60018303838381613a7957613a796157b8565b06149392505050565b5f81604051602001613a949190615cfd565b604051602081830303815290604052805190602001209050919050565b5f613aba614930565b613acd86868560e00151875f0151613fbe565b91508163ffffffff165f03613b8e57600285018054600163ffffffff600160c01b80840482168381019092160263ffffffff60c01b1990931692909217928390556001600160401b03600160401b9093049290921660e08401529250829003613b4c578351815260808301516001600160a01b0316606082015261136d565b6101008301516001600160401b03165f9081526001870160209081526040808320875184529091529020805463ffffffff191663ffffffff841617905561136d565b5060e0808301516001600160401b039081165f90815260028089016020908152604080842063ffffffff8816855282529283902083516101408101855281548152600182015492810192909252918201549281019290925260038101546001600160a01b0380821660608501526001600160601b03600160a01b9283900481166080860152600484015491821660a08601529190041660c0830152600501549182169281019290925261ffff600160401b82041661010083015260ff600160501b9091041661012082015294509492505050565b5f80603c8302613c728686614429565b0142101595945050505050565b60a08401515f906001600160a01b031615613d2757816101a0015115613cd857613cb58560c001516001600160601b031661443e565b9050613cd388866060015187608001516001600160601b0316614097565b613df5565b6002613cf086608001516001600160601b031661443e565b901c9050613cd3888660a00151836003613d0a9190615d0c565b8860c001516001600160601b0316613d229190615a58565b614097565b816101a0015115613d4b57604051639d49773160e01b815260040160405180910390fd5b613d6185608001516001600160601b031661443e565b90508160c001516001600160601b03165f14613df5576001860180546001600160a01b031690556020830151613d98908390614460565b15613df557336001600160a01b031682608001516001600160a01b031603613dd95760c0820151613dd2906001600160601b031682615a58565b9050613df5565b613df58883608001518460c001516001600160601b0316614097565b8160200151602001516001600160601b0316811115613e3157613e2c88338460200151602001516001600160601b03168403614097565b613e69565b8160200151602001516001600160601b0316811015613e6957613e69888833848660200151602001516001600160601b031603613ebf565b60208083015101516001600160601b031660808601525f60a0860152336060860152825161ffff166101008601526101a0820151612969576020808501519086015260a082015160408601525050505050505050565b6001600160a01b0382165f908152600685016020526040902054818110613f3d576001600160a01b0383165f818152600687016020526040908190208484039055517f85f32beeaff2d0019a8d196f06790c9a652191759c46643311344fd38920423c90613f309085815260200190565b60405180910390a2610a41565b613f468461431f565b6040516323b872dd60e01b81526001600160a01b0385811660048301523060248301526044820185905291909116906323b872dd906064016020604051808303815f875af1158015613f9a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061296d9190615a6b565b6001600160401b0382165f90815260028501602090815260408083206001845290915281205482900361402557506002830154600190600160c01b900463ffffffff168110614020576040516367a1907f60e01b815260040160405180910390fd5b612fa4565b5060028301546001600160401b03165f908152600185016020908152604080832084845290915290205463ffffffff1680158015906140795750600284015463ffffffff600160c01b909104811690821610155b15612fa4576040516367a1907f60e01b815260040160405180910390fd5b6001600160a01b0382165f908152600684016020526040812080548392906140c0908490615a58565b90915550506040518181526001600160a01b038316907f6de6fe586196fa05b73b973026c5fda3968a2933989bff3a0b6bd57644fab6069060200160405180910390a2505050565b5f54610100900460ff1661412e5760405162461bcd60e51b81526004016107a790615d23565b6141366144d0565b6141546001600160a01b0382161561414e5781613064565b33613064565b5060c9805461ff001916610100179055565b5f54610100900460ff1661418c5760405162461bcd60e51b81526004016107a790615d23565b6001600160401b034611156141b45760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381163b6142435760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016107a7565b5f80516020615dd683398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b61427a836144f6565b5f825111806142865750805b1561092d576129708383614535565b6142a960c954610100900460ff1660021490565b6142c65760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001612bde565b604051635437cecf60e11b81526a3a30b4b5b7afba37b5b2b760a91b60048201525f60248201819052906001600160a01b0383169063a86f9d9e90604401602060405180830381865afa158015614378573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610db691906157f1565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f805f6143fa858561455a565b91509150612e5e8161459c565b610c4382825a6146e5565b5f617e2c8210158015610db6575050617e90101590565b5f8183116144375781610b1e565b5090919050565b5f8115614459576003614452836007615d0c565b901c610db6565b5f92915050565b5f826101800151801561447e575082610120015163ffffffff166001145b80610b1e57508261016001518015614497575081516020145b8015610b1e57507f20d34d7a20a139f9be221ba2163925c0c86ed02d34033f288f010d23a63ef4b76144c883615d6e565b149392505050565b5f54610100900460ff16610ec85760405162461bcd60e51b81526004016107a790615d23565b6144ff816141d6565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b1e8383604051806060016040528060278152602001615df660279139614728565b5f80825160410361458e576020830151604084015160608501515f1a6145828782858561479c565b94509450505050614595565b505f905060025b9250929050565b5f8160048111156145af576145af615d94565b036145b75750565b60018160048111156145cb576145cb615d94565b036146185760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016107a7565b600281600481111561462c5761462c615d94565b036146795760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016107a7565b600381600481111561468d5761468d615d94565b03610b0c5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016107a7565b815f036146f157505050565b61470b83838360405180602001604052805f815250614856565b61092d57604051634c67134d60e11b815260040160405180910390fd5b60605f80856001600160a01b0316856040516147449190615da8565b5f60405180830381855af49150503d805f811461477c576040519150601f19603f3d011682016040523d82523d5f602084013e614781565b606091505b509150915061479286838387614893565b9695505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156147d157505f9050600361136d565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614822573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661484a575f6001925092505061136d565b965f9650945050505050565b5f6001600160a01b03851661487e57604051634c67134d60e11b815260040160405180910390fd5b5f80835160208501878988f195945050505050565b606083156149015782515f036148fa576001600160a01b0385163b6148fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107a7565b5081612fa4565b612fa483838151156149165781518083602001fd5b8060405162461bcd60e51b81526004016107a79190615dc3565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080516101c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b604051806101c00160405280614a45614983565b81526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e082018190526101008201819052610120820181905261014082018190526101609091015290565b604051806101a00160405280614b17614983565b81525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082018190526101208201819052610140820181905261016082018190526101809091015290565b6040518060600160405280614b88614983565b81526040805160c0810182525f808252602080830182905282840182905260608084018390526080840181905260a084015284019190915291015290565b80356001600160401b0381168114614bdc575f80fd5b919050565b5f8083601f840112614bf1575f80fd5b5081356001600160401b03811115614c07575f80fd5b602083019150836020828501011115614595575f80fd5b5f805f60408486031215614c30575f80fd5b614c3984614bc6565b925060208401356001600160401b03811115614c53575f80fd5b614c5f86828701614be1565b9497909650939450505050565b6001600160a01b0381168114610b0c575f80fd5b8035614bdc81614c6c565b8015158114610b0c575f80fd5b8035614bdc81614c8b565b5f805f8060808587031215614cb6575f80fd5b8435614cc181614c6c565b93506020850135614cd181614c6c565b9250604085013591506060850135614ce881614c8b565b939692955090935050565b5f60208284031215614d03575f80fd5b8135610b1e81614c6c565b5f805f60608486031215614d20575f80fd5b614d2984614bc6565b9250602084013591506040840135614d4081614c8b565b809150509250925092565b5f60208284031215614d5b575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715614d9857614d98614d62565b60405290565b6040516101c081016001600160401b0381118282101715614d9857614d98614d62565b60405160c081016001600160401b0381118282101715614d9857614d98614d62565b604051601f8201601f191681016001600160401b0381118282101715614e0b57614e0b614d62565b604052919050565b5f82601f830112614e22575f80fd5b81356001600160401b03811115614e3b57614e3b614d62565b614e4e601f8201601f1916602001614de3565b818152846020838601011115614e62575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614e8f575f80fd5b8235614e9a81614c6c565b915060208301356001600160401b03811115614eb4575f80fd5b614ec085828601614e13565b9150509250929050565b803563ffffffff81168114614bdc575f80fd5b5f8060408385031215614eee575f80fd5b614ef783614bc6565b9150614f0560208401614eca565b90509250929050565b5f610140820190508251825260208301516020830152604083015160408301526060830151614f4860608401826001600160a01b03169052565b506080830151614f6360808401826001600160601b03169052565b5060a0830151614f7e60a08401826001600160a01b03169052565b5060c0830151614f9960c08401826001600160601b03169052565b5060e0830151614fb460e08401826001600160401b03169052565b506101008381015161ffff16908301526101209283015160ff16929091019190915290565b5f60208284031215614fe9575f80fd5b610b1e82614bc6565b815181526020808301516001600160a01b0316908201526040808301516001600160601b0316908201526060808301516001600160401b039081169183019190915260808084015182169083015260a080840151918216908301526101008201905060c083015161506b60c084018263ffffffff169052565b5060e083015161508360e084018263ffffffff169052565b5092915050565b5f806040838503121561509b575f80fd5b8235915060208301356150ad81614c8b565b809150509250929050565b6001600160401b0380825116835280602083015116602084015260408201511515604084015260ff606083015116606084015261ffff608083015116608084015263ffffffff60a08301511660a08401528060c08301511660c0840152505050565b838152610180810161515d602083018580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b612fa460a08301846150b8565b5f610100820190506001600160401b038084511683528060208501511660208401528060408501511660408401528060608501511660608401525063ffffffff608084015116608083015260a08301516151cf60a08401826001600160601b03169052565b5060c08301516151e460c084018260ff169052565b5060e083015161508360e084018215159052565b6101608101615235828580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b610b1e60808301846150b8565b5f805f8060408587031215615255575f80fd5b84356001600160401b038082111561526b575f80fd5b61527788838901614be1565b9096509450602087013591508082111561528f575f80fd5b5061529c87828801614be1565b95989497509550505050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a08101516152ee60a08401826001600160a01b03169052565b5060c081015161530960c08401826001600160401b03169052565b5060e081015161532160e084018263ffffffff169052565b50610100818101516001600160401b039081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015115159083015261018080820151908301526101a0808201516001600160a01b03811682850152612970565b5f815180845260208085019450602084015f5b838110156153ea57815180516001600160a01b03168852838101516001600160601b0316848901526040908101516001600160401b0316908801526060909601959082019060010161539d565b509495945050505050565b5f6101e061540383866152a8565b806101c08401526154168184018561538a565b95945050505050565b5f8060408385031215615430575f80fd5b61543983614bc6565b946020939093013593505050565b5f60208284031215615457575f80fd5b8135610b1e81614c8b565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b5f60e08201905082546001600160401b038082168452808260401c1660208501525060ff8160801c161515604084015260ff8160881c16606084015261ffff8160901c16608084015263ffffffff8160a01c1660a08401528060c01c60c08401525092915050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b61ffff81168114610b0c575f80fd5b8035614bdc816155b0565b5f608082840312156155da575f80fd5b604051608081018181106001600160401b03821117156155fc576155fc614d62565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b5f6040828403121561563d575f80fd5b615645614d76565b90508135615652816155b0565b815260208201356001600160401b0381111561566c575f80fd5b61567884828501614e13565b60208301525092915050565b5f805f838503610260811215615698575f80fd5b6101c0808212156156a7575f80fd5b6156af614d9e565b915085358252602086013560208301526040860135604083015260608601356060830152608086013560808301526156e960a08701614c80565b60a08301526156fa60c08701614bc6565b60c083015261570b60e08701614eca565b60e083015261010061571e818801614bc6565b90830152610120615730878201614bc6565b908301526101406157428782016155bf565b90830152610160615754878201614c98565b9083015261018086810135908301526101a0615771818801614c80565b8184015250819450615785878288016155ca565b935050506102408401356001600160401b038111156157a2575f80fd5b6157ae8682870161562d565b9150509250925092565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b03808416806157e5576157e56157b8565b92169190910692915050565b5f60208284031215615801575f80fd5b8151610b1e81614c6c565b80516001600160601b0381168114614bdc575f80fd5b5f60c08284031215615832575f80fd5b61583a614dc1565b8251815261584a6020840161580c565b602082015261585b6040840161580c565b6040820152606083015162ffffff81168114615875575f80fd5b60608201526080830151615888816155b0565b608082015260a083015160ff811681146158a0575f80fd5b60a08201529392505050565b5f5b838110156158c65781810151838201526020016158ae565b50505f910152565b5f81518084526158e58160208601602086016158ac565b601f01601f19169290920160200192915050565b61ffff81511682525f602082015160406020850152612fa460408501826158ce565b83518152602080850151818301526040808601516001600160a01b03908116828501526060808801516001600160401b03168186015260808089015115159086015260a08089015115159086015260c08089015190921691850191909152855160e0850152918501516101008401528401516101208301528301516101408201525f61018080610160840152614792818401856158f9565b845181526020808601519082015260408086015190820152606094850151948101949094526001600160a01b039290921660808401526001600160601b031660a083015261ffff1660c082015260e00190565b634e487b7160e01b5f52600160045260245ffd5b5f82615a2857615a286157b8565b500690565b5f60208284031215615a3d575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610db657610db6615a44565b5f60208284031215615a7b575f80fd5b8151610b1e81614c8b565b81810381811115610db657610db6615a44565b5f82601f830112615aa8575f80fd5b813560206001600160401b0380831115615ac457615ac4614d62565b8260051b615ad3838201614de3565b9384528581018301938381019088861115615aec575f80fd5b84880192505b85831015615b6957823584811115615b08575f80fd5b88016040818b03601f1901811315615b1e575f80fd5b615b26614d76565b87830135615b3381614c6c565b8152908201359086821115615b46575f80fd5b615b548c8984860101614e13565b81890152845250509184019190840190615af2565b98975050505050505050565b5f60208284031215615b85575f80fd5b81356001600160401b0380821115615b9b575f80fd5b9083019060c08286031215615bae575f80fd5b615bb6614dc1565b615bbf83614c80565b8152615bcd60208401614c80565b60208201526040830135604082015260608301356060820152608083013582811115615bf7575f80fd5b615c0387828601615a99565b60808301525060a083013582811115615c1a575f80fd5b615c2687828601614e13565b60a08301525095945050505050565b6001600160401b0381811683821601908082111561508357615083615a44565b6001600160401b0382811682821603908082111561508357615083615a44565b818382375f9101908152919050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b5f60208284031215615cc2575f80fd5b8151610b1e816155b0565b5f6102006001600160601b0386168352615cea60208401866152a8565b806101e08401526147928184018561538a565b6101c08101610db682846152a8565b8082028115828204841417610db657610db6615a44565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b80516020808301519190811015615d8e575f198160200360031b1b821691505b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f8251615db98184602087016158ac565b9190910192915050565b602081525f610b1e60208301846158ce56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220db2a18e7a705df631f0e11429aeb2220aa6c2c995a693e956c7178e18898c5c764736f6c63430008180033
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.