Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
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:
TaikoL1
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 "../common/EssentialContract.sol"; import "./libs/LibProposing.sol"; import "./libs/LibProving.sol"; import "./libs/LibVerifying.sol"; import "./ITaikoL1.sol"; import "./TaikoErrors.sol"; import "./TaikoEvents.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, TaikoEvents, TaikoErrors { /// @notice The TaikoL1 state. TaikoData.State public state; uint256[50] private __gap; modifier whenProvingNotPaused() { if (state.slotB.provingPaused) revert L1_PROVING_PAUSED(); _; } modifier emitEventForClient() { _; LibVerifying.emitEventForClient(state); } /// @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); LibVerifying.init(state, getConfig(), _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, _checkEOAForCalldataDA() ); if (!state.slotB.provingPaused) { LibVerifying.verifyBlocks(state, config, this, config.maxBlocksToVerifyPerProposal); } } /// @inheritdoc ITaikoL1 function proveBlock( uint64 _blockId, bytes calldata _input ) external whenNotPaused whenProvingNotPaused nonReentrant emitEventForClient { ( 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 L1_INVALID_BLOCK_ID(); TaikoData.Config memory config = getConfig(); uint8 maxBlocksToVerify = LibProving.proveBlock(state, config, this, meta, tran, proof); LibVerifying.verifyBlocks(state, config, this, maxBlocksToVerify); } /// @inheritdoc ITaikoL1 function verifyBlocks(uint64 _maxBlocksToVerify) external whenNotPaused whenProvingNotPaused nonReentrant emitEventForClient { LibVerifying.verifyBlocks(state, getConfig(), this, _maxBlocksToVerify); } /// @notice Pause block proving. /// @param _pause True if paused. function pauseProving(bool _pause) external { _authorizePause(msg.sender, _pause); LibProving.pauseProving(state, _pause); } /// @inheritdoc EssentialContract function unpause() public override { super.unpause(); // permission checked inside state.slotB.lastUnpausedAt = uint64(block.timestamp); } /// @notice Gets the details of a block. /// @param _blockId Index of the block. /// @return blk_ The block. function getBlock(uint64 _blockId) public 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 ) public 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 ) public view returns (TaikoData.TransitionState memory) { return LibUtils.getTransition(state, getConfig(), _blockId, _tid); } /// @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() public view returns (TaikoData.SlotA memory, TaikoData.SlotB memory) { return (state.slotA, state.slotB); } /// @notice Gets SlotA /// @return State variables stored at SlotA. function slotA() public view returns (TaikoData.SlotA memory) { return state.slotA; } /// @notice Gets SlotB /// @return State variables stored at SlotB. function slotB() public view returns (TaikoData.SlotB memory) { return state.slotB; } /// @inheritdoc ITaikoL1 function getConfig() public view 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, // Assume the block time is 3s, the protocol will allow ~90 days of // new blocks without any verification. blockMaxProposals: 3_000_000, blockRingBufferSize: 3_010_000, // Can be overridden by the tier config. maxBlocksToVerifyPerProposal: 10, // 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. blockMaxGasLimit: 240_000_000, livenessBond: 250e18, // 250 Taiko token blockSyncThreshold: 16 }); } /// @dev chain_pauser is supposed to be a cold wallet. function _authorizePause( address, bool ) internal view virtual override onlyFromOwnerOrNamed(LibStrings.B_CHAIN_WATCHDOG) { } function _checkEOAForCalldataDA() internal pure virtual returns (bool) { return true; } }
// 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 REENTRANT_CALL(); error INVALID_PAUSE_STATUS(); error ZERO_ADDR_MANAGER(); /// @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 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(); _; } /// @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); } /// @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; } /// @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 onlyInitializing { if (_addressManager == address(0)) revert ZERO_ADDR_MANAGER(); __Essential_init(_owner); __AddressResolver_init(_addressManager); } function __Essential_init(address _owner) internal virtual { _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; } } function _inNonReentrant() internal view returns (bool) { return _loadReentryLock() == _TRUE; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../../common/IAddressResolver.sol"; import "../../common/LibStrings.sol"; import "../../libs/LibAddress.sol"; import "../../libs/LibNetwork.sol"; import "../hooks/IHook.sol"; import "../tiers/ITierProvider.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; // Warning: Any events defined here must also be defined in TaikoEvents.sol. /// @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 ); // Warning: Any errors defined here must also be defined in TaikoErrors.sol. error L1_BLOB_NOT_AVAILABLE(); error L1_BLOB_NOT_FOUND(); error L1_INVALID_HOOK(); error L1_INVALID_PROVER(); error L1_INVALID_SIG(); error L1_LIVENESS_BOND_NOT_RECEIVED(); error L1_TOO_MANY_BLOCKS(); error L1_UNAUTHORIZED(); 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, bool _checkEOAForCalldataDA ) internal returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_) { TaikoData.BlockParams memory params = abi.decode(_data, (TaikoData.BlockParams)); // We need a prover that will submit proofs after the block has been submitted if (params.assignedProver == address(0)) { revert L1_INVALID_PROVER(); } if (params.coinbase == address(0)) { params.coinbase = msg.sender; } // Taiko, as a Based Rollup, enables permissionless block proposals. // However, if the "proposer" address is set to a non-zero value, we // ensure that only that specific address has the authority to propose // blocks. TaikoData.SlotB memory b = _state.slotB; if (!_isProposerPermitted(b, _resolver)) revert L1_UNAUTHORIZED(); // It's essential to ensure that the ring buffer for proposed blocks // still has space for at least one more block. if (b.numBlocks >= b.lastVerifiedBlockId + _config.blockMaxProposals + 1) { revert L1_TOO_MANY_BLOCKS(); } bytes32 parentMetaHash = _state.blocks[(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 (params.parentMetaHash != 0 && parentMetaHash != 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: params.extraData, depositsHash: _EMPTY_ETH_DEPOSIT_HASH, coinbase: params.coinbase, id: 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: 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 ( _checkEOAForCalldataDA && meta_.id != 1 && ECDSA.recover(meta_.blobHash, params.signature) != msg.sender ) { revert L1_INVALID_SIG(); } } // 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, b.numBlocks, block.number)); // Use the difficulty as a random number meta_.minTier = ITierProvider(_resolver.resolve(LibStrings.B_TIER_PROVIDER, false)) .getMinTier(uint256(meta_.difficulty)); // Create the block that will be stored onchain TaikoData.Block memory blk = TaikoData.Block({ metaHash: keccak256(abi.encode(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. livenessBond: _config.livenessBond, blockId: 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, assignedProver: params.assignedProver }); // Store the block in the ring buffer _state.blocks[b.numBlocks % _config.blockRingBufferSize] = blk; // Increment the counter (cursor) by 1. unchecked { ++_state.slotB.numBlocks; } { IERC20 tko = IERC20(_resolver.resolve(LibStrings.B_TAIKO_TOKEN, false)); uint256 tkoBalance = tko.balanceOf(address(this)); // Run all hooks. // Note that address(this).balance has been updated with msg.value, // prior to any code in this function has been executed. address prevHook; for (uint256 i; i < params.hookCalls.length; ++i) { if (uint160(prevHook) >= uint160(params.hookCalls[i].hook)) { revert L1_INVALID_HOOK(); } // When a hook is called, all ether in this contract will be sent to the hook. // If the ether sent to the hook is not used entirely, the hook shall send the Ether // back to this contract for the next hook to use. // Proposers shall choose to use extra hooks wisely. IHook(params.hookCalls[i].hook).onBlockProposed{ value: address(this).balance }( blk, meta_, params.hookCalls[i].data ); prevHook = params.hookCalls[i].hook; } // Refund Ether if (address(this).balance != 0) { msg.sender.sendEtherAndVerify(address(this).balance); } // Check that after hooks, the Taiko Token balance of this contract // have increased by the same amount as _config.livenessBond (to prevent) // multiple draining payments by a malicious proposer nesting the same // hook. if (tko.balanceOf(address(this)) != tkoBalance + _config.livenessBond) { revert L1_LIVENESS_BOND_NOT_RECEIVED(); } } deposits_ = new TaikoData.EthDeposit[](0); emit BlockProposed({ blockId: blk.blockId, assignedProver: blk.assignedProver, livenessBond: _config.livenessBond, meta: meta_, depositsProcessed: deposits_ }); } function _isProposerPermitted( TaikoData.SlotB memory _slotB, IAddressResolver _resolver ) private view returns (bool) { if (_slotB.numBlocks == 1) { // Only proposer_one can propose the first block after genesis address proposerOne = _resolver.resolve(LibStrings.B_PROPOSER_ONE, true); if (proposerOne != address(0)) { return msg.sender == proposerOne; } } address proposer = _resolver.resolve(LibStrings.B_PROPOSER, true); return proposer == address(0) || msg.sender == proposer; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../../common/IAddressResolver.sol"; import "../../common/LibStrings.sol"; import "../../verifiers/IVerifier.sol"; import "../tiers/ITierProvider.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; using SafeERC20 for IERC20; // 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; bytes32 metaHash; address assignedProver; uint96 livenessBond; uint64 slot; uint64 blockId; uint32 tid; bool lastUnpausedAt; bool isTopTier; bool inProvingWindow; bool sameTransition; } // Warning: Any events defined here must also be defined in TaikoEvents.sol. /// @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); // Warning: Any errors defined here must also be defined in TaikoErrors.sol. error L1_ALREADY_CONTESTED(); error L1_ALREADY_PROVED(); error L1_BLOCK_MISMATCH(); error L1_CANNOT_CONTEST(); error L1_INVALID_BLOCK_ID(); error L1_INVALID_PAUSE_STATUS(); error L1_INVALID_TIER(); error L1_INVALID_TRANSITION(); error L1_NOT_ASSIGNED_PROVER(); /// @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 _meta The block's metadata. /// @param _tran The transition data. /// @param _proof The proof. /// @return The number of blocks to be verified with this transaction. function proveBlock( TaikoData.State storage _state, TaikoData.Config memory _config, IAddressResolver _resolver, TaikoData.BlockMetadata memory _meta, TaikoData.Transition memory _tran, TaikoData.TierProof memory _proof ) internal returns (uint8) { // 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 L1_INVALID_BLOCK_ID(); } local.slot = _meta.id % _config.blockRingBufferSize; TaikoData.Block storage blk = _state.blocks[local.slot]; local.blockId = blk.blockId; local.assignedProver = blk.assignedProver; 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 != keccak256(abi.encode(_meta))) { revert 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 storage 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. local.tier = ITierProvider(_resolver.resolve(LibStrings.B_TIER_PROVIDER, false)).getTier(_proof.tier); local.inProvingWindow = !LibUtils.isPostDeadline(ts.timestamp, local.b.lastUnpausedAt, local.tier.provingWindow); // Checks if only the assigned prover is permissioned to prove the block. // The guardian 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; IERC20 tko = IERC20(_resolver.resolve(LibStrings.B_TAIKO_TOKEN, false)); local.livenessBond = blk.livenessBond; if (local.isTopTier) { if (local.livenessBond != 0) { if ( local.inProvingWindow || ( _proof.data.length == 32 && bytes32(_proof.data) == LibStrings.H_RETURN_LIVENESS_BOND ) ) { tko.safeTransfer(local.assignedProver, local.livenessBond); } blk.livenessBond = 0; local.livenessBond = 0; } } local.sameTransition = _tran.blockHash == ts.blockHash && _tran.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(blk, ts, _tran, _proof, local, tko); 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 = _tran.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. tko.safeTransferFrom(msg.sender, address(this), 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); return local.tier.maxBlocksToVerifyPerProof; } /// @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 storage 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_ = _state.transitions[_local.slot][tid_]; ts_.blockHash = 0; ts_.stateRoot = 0; ts_.validityBond = 0; ts_.contester = address(0); ts_.contestBond = 1; // to save gas ts_.timestamp = _blk.proposedAt; ts_.tier = 0; ts_.__reserved1 = 0; 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 { // In scenarios where this transition is not the first one, we // straightforwardly reset the transition prover to address // zero. ts_.prover = address(0); // 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. _state.transitionIds[_local.blockId][_tran.parentHash] = tid_; // There is no need to initialize ts.key here because it's only used when tid == 1 } } 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.Block storage _blk, TaikoData.TransitionState storage _ts, TaikoData.Transition memory _tran, TaikoData.TierProof memory _proof, Local memory _local, IERC20 _tko ) 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. _tko.safeTransfer(_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; _tko.safeTransfer(_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) { if (_local.assignedProver == msg.sender && _local.inProvingWindow) { unchecked { reward += _local.livenessBond; } } _blk.livenessBond = 0; _local.livenessBond = 0; } } unchecked { if (reward > _local.tier.validityBond) { _tko.safeTransfer(msg.sender, reward - _local.tier.validityBond); } else if (reward < _local.tier.validityBond) { _tko.safeTransferFrom(msg.sender, address(this), _local.tier.validityBond - reward); } } _ts.validityBond = _local.tier.validityBond; _ts.contestBond = 1; // to save gas _ts.contester = address(0); _ts.prover = msg.sender; _ts.tier = _proof.tier; if (!_local.sameTransition) { _ts.blockHash = _tran.blockHash; _ts.stateRoot = _tran.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; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../../common/IAddressResolver.sol"; import "../../common/LibStrings.sol"; import "../../signal/ISignalService.sol"; import "../tiers/ITierProvider.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; using SafeERC20 for IERC20; // Warning: Any events defined here must also be defined in TaikoEvents.sol. /// @notice Emitted when a block is verified. /// @param blockId The block ID. /// @param prover The actual prover of the block. /// @param blockHash The block hash. /// @param stateRoot The state root. /// @param tier The tier of the transition used for verification. event BlockVerified( uint256 indexed blockId, address indexed prover, bytes32 blockHash, bytes32 stateRoot, uint16 tier ); /// @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); // Warning: Any errors defined here must also be defined in TaikoErrors.sol. error L1_BLOCK_MISMATCH(); error L1_INVALID_CONFIG(); error L1_INVALID_GENESIS_HASH(); error L1_TRANSITION_ID_ZERO(); /// @notice Initializes the Taiko protocol state. /// @param _state The state to initialize. /// @param _config The configuration for the Taiko protocol. /// @param _genesisBlockHash The block hash of the genesis block. function init( TaikoData.State storage _state, TaikoData.Config memory _config, bytes32 _genesisBlockHash ) internal { if (!_isConfigValid(_config)) revert L1_INVALID_CONFIG(); 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 Verifies up to N blocks. function verifyBlocks( TaikoData.State storage _state, TaikoData.Config memory _config, IAddressResolver _resolver, uint64 _maxBlocksToVerify ) internal { if (_maxBlocksToVerify == 0) { return; } // Retrieve the latest verified block and the associated transition used // for its verification. TaikoData.SlotB memory b = _state.slotB; uint64 blockId = b.lastVerifiedBlockId; uint64 slot = blockId % _config.blockRingBufferSize; TaikoData.Block storage blk = _state.blocks[slot]; if (blk.blockId != blockId) revert L1_BLOCK_MISMATCH(); uint32 tid = blk.verifiedTransitionId; // The following scenario should never occur but is included as a // precaution. if (tid == 0) revert L1_TRANSITION_ID_ZERO(); // The `blockHash` variable represents the most recently trusted // blockHash on L2. bytes32 blockHash = _state.transitions[slot][tid].blockHash; bytes32 stateRoot; uint64 numBlocksVerified; address tierProvider; IERC20 tko = IERC20(_resolver.resolve(LibStrings.B_TAIKO_TOKEN, false)); // 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 { ++blockId; while (blockId < b.numBlocks && numBlocksVerified < _maxBlocksToVerify) { slot = blockId % _config.blockRingBufferSize; blk = _state.blocks[slot]; if (blk.blockId != blockId) revert L1_BLOCK_MISMATCH(); tid = LibUtils.getTransitionId(_state, blk, slot, 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 (tid == 0) break; // A transition with the correct `parentHash` has been located. TaikoData.TransitionState storage ts = _state.transitions[slot][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. if (ts.contester != address(0)) { break; } else { if (tierProvider == address(0)) { tierProvider = _resolver.resolve(LibStrings.B_TIER_PROVIDER, false); } if ( !LibUtils.isPostDeadline( ts.timestamp, b.lastUnpausedAt, ITierProvider(tierProvider).getTier(ts.tier).cooldownWindow ) ) { // If cooldownWindow is 0, the block can theoretically // be proved and verified within the same L1 block. break; } } // Mark this block as verified blk.verifiedTransitionId = tid; // Update variables blockHash = ts.blockHash; stateRoot = ts.stateRoot; tko.safeTransfer(ts.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 BlockVerified({ blockId: blockId, prover: ts.prover, blockHash: blockHash, stateRoot: stateRoot, tier: ts.tier }); ++blockId; ++numBlocksVerified; } if (numBlocksVerified != 0) { uint64 lastVerifiedBlockId = b.lastVerifiedBlockId + numBlocksVerified; // Update protocol level state variables _state.slotB.lastVerifiedBlockId = lastVerifiedBlockId; // Sync chain data _syncChainData(_state, _config, _resolver, lastVerifiedBlockId, stateRoot); } } } /// @notice Emit events used by client/node. function emitEventForClient(TaikoData.State storage _state) internal { emit StateVariablesUpdated({ slotB: _state.slotB }); } function _syncChainData( TaikoData.State storage _state, TaikoData.Config memory _config, IAddressResolver _resolver, uint64 _lastVerifiedBlockId, bytes32 _stateRoot ) private { ISignalService signalService = ISignalService(_resolver.resolve(LibStrings.B_SIGNAL_SERVICE, false)); (uint64 lastSyncedBlock,) = signalService.getSyncedChainData( _config.chainId, LibStrings.H_STATE_ROOT, 0 /* latest block Id*/ ); if (_lastVerifiedBlockId > lastSyncedBlock + _config.blockSyncThreshold) { _state.slotA.lastSyncedBlockId = _lastVerifiedBlockId; _state.slotA.lastSynecdAt = uint64(block.timestamp); signalService.syncChainData( _config.chainId, LibStrings.H_STATE_ROOT, _lastVerifiedBlockId, _stateRoot ); } } function _isConfigValid(TaikoData.Config memory _config) private view returns (bool) { if ( _config.chainId <= 1 || _config.chainId == block.chainid // || _config.blockMaxProposals <= 1 || _config.blockRingBufferSize <= _config.blockMaxProposals + 1 || _config.blockMaxGasLimit == 0 || _config.livenessBond == 0 ) return false; return true; } }
// 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 Gets the configuration of the TaikoL1 contract. /// @return Config struct containing configuration parameters. function getConfig() external view returns (TaikoData.Config memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title TaikoErrors /// @notice This abstract contract provides custom error declarations used in /// the Taiko protocol. Each error corresponds to specific situations where /// exceptions might be thrown. /// @dev The errors defined here must match the definitions in the corresponding /// L1 libraries. /// @custom:security-contact [email protected] abstract contract TaikoErrors { error L1_ALREADY_CONTESTED(); error L1_ALREADY_PROVED(); error L1_BLOB_NOT_AVAILABLE(); error L1_BLOB_NOT_FOUND(); error L1_BLOCK_MISMATCH(); error L1_CANNOT_CONTEST(); error L1_INVALID_BLOCK_ID(); error L1_INVALID_CONFIG(); error L1_INVALID_GENESIS_HASH(); error L1_INVALID_HOOK(); error L1_INVALID_PARAM(); error L1_INVALID_PAUSE_STATUS(); error L1_INVALID_PROVER(); error L1_INVALID_SIG(); error L1_INVALID_TIER(); error L1_INVALID_TRANSITION(); error L1_LIVENESS_BOND_NOT_RECEIVED(); error L1_NOT_ASSIGNED_PROVER(); error L1_PROVING_PAUSED(); error L1_RECEIVE_DISABLED(); error L1_TOO_MANY_BLOCKS(); error L1_TRANSITION_ID_ZERO(); error L1_TRANSITION_NOT_FOUND(); error L1_UNAUTHORIZED(); error L1_UNEXPECTED_PARENT(); error L1_UNEXPECTED_TRANSITION_ID(); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./TaikoData.sol"; /// @title TaikoEvents /// @notice This abstract contract provides event declarations for the Taiko /// protocol, which are emitted during block proposal, proof, verification, and /// Ethereum deposit processes. /// @dev The events defined here must match the definitions in the corresponding /// L1 libraries. /// @custom:security-contact [email protected] abstract contract TaikoEvents { /// @dev Emitted when a block is proposed. /// @param blockId The ID of the proposed block. /// @param assignedProver The block's assigned prover. /// @param livenessBond The bond in Taiko token from the assigned prover. /// @param meta The block metadata containing information about the proposed /// block. /// @param depositsProcessed Ether deposits processed. event BlockProposed( uint256 indexed blockId, address indexed assignedProver, uint96 livenessBond, TaikoData.BlockMetadata meta, TaikoData.EthDeposit[] depositsProcessed ); /// @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 The block's state root. /// @param tier The tier ID of the proof. event BlockVerified( uint256 indexed blockId, address indexed prover, bytes32 blockHash, bytes32 stateRoot, uint16 tier ); /// @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); /// @dev Emitted when a block transition is proved or re-proved. /// @param blockId The ID of the proven block. /// @param tran The verified transition. /// @param prover The prover address. /// @param validityBond The validity bond amount. /// @param tier The tier ID of the proof. event TransitionProved( uint256 indexed blockId, TaikoData.Transition tran, address prover, uint96 validityBond, uint16 tier ); /// @dev Emitted when a block transition is contested. /// @param blockId The ID of the proven block. /// @param tran The verified transition. /// @param contester The contester address. /// @param contestBond The contesting bond amount. /// @param tier The tier ID of the proof. event TransitionContested( uint256 indexed blockId, TaikoData.Transition tran, address contester, uint96 contestBond, uint16 tier ); /// @dev Emitted when proving has been paused /// @param paused True if paused, false if unpaused. event ProvingPaused(bool paused); /// @dev Emitted when an Ethereum deposit is made. /// @param deposit The Ethereum deposit information including recipient, /// amount, and ID. event EthDeposited(TaikoData.EthDeposit deposit); }
// 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(); _; } /// @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 = 167_000; /// @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; } /// @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 isTaikoDevnetL1(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 || isTaikoDevnetL1(_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 // 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 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 pragma solidity 0.8.24; /// @title LibStrings /// @custom:security-contact [email protected] library LibStrings { bytes32 internal constant B_CHAIN_WATCHDOG = bytes32("chain_watchdog"); bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer"); bytes32 internal constant B_PROPOSER = bytes32("proposer"); bytes32 internal constant B_PROPOSER_ONE = bytes32("proposer_one"); bytes32 internal constant B_SIGNAL_SERVICE = bytes32("signal_service"); bytes32 internal constant B_TAIKO_TOKEN = bytes32("taiko_token"); bytes32 internal constant B_TAIKO = bytes32("taiko"); bytes32 internal constant B_BRIDGE = bytes32("bridge"); bytes32 internal constant B_ERC20_VAULT = bytes32("erc20_vault"); bytes32 internal constant B_BRIDGED_ERC20 = bytes32("bridged_erc20"); bytes32 internal constant B_ERC1155_VAULT = bytes32("erc1155_vault"); bytes32 internal constant B_BRIDGED_ERC1155 = bytes32("bridged_erc1155"); bytes32 internal constant B_ERC721_VAULT = bytes32("erc721_vault"); bytes32 internal constant B_BRIDGED_ERC721 = bytes32("bridged_erc721"); bytes32 internal constant B_BRIDGE_WATCHDOG = bytes32("bridge_watchdog"); bytes32 internal constant B_SGX_WATCHDOG = bytes32("sgx_watchdog"); bytes32 internal constant B_TIER_PROVIDER = bytes32("tier_provider"); bytes32 internal constant B_TIER_SGX = bytes32("tier_sgx"); bytes32 internal constant B_TIER_SGX_ZKVM = bytes32("tier_sgx_zkvm"); bytes32 internal constant B_TIER_GUARDIAN_MINORITY = bytes32("tier_guardian_minority"); bytes32 internal constant B_TIER_GUARDIAN = bytes32("tier_guardian"); bytes32 internal constant B_AUTOMATA_DCAP_ATTESTATION = bytes32("automata_dcap_attestation"); bytes32 internal constant B_PROVER_ASSIGNMENT = bytes32("PROVER_ASSIGNMENT"); bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND"); bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT"); bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT"); string internal constant S_SIGNAL = "SIGNAL"; }
// 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 { bytes4 private constant _EIP1271_MAGICVALUE = 0x1626ba7e; 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 "../TaikoData.sol"; /// @title IHook /// @custom:security-contact [email protected] interface IHook { /// @notice Called when a block is proposed. /// @param _blk The proposed block. /// @param _meta The metadata of the proposed block. /// @param _data The data of the proposed block. function onBlockProposed( TaikoData.Block calldata _blk, TaikoData.BlockMetadata calldata _meta, bytes calldata _data ) external payable; }
// 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; } 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 rand (Semi) random number. /// @return The tier id. function getMinTier(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 + 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 // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// 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; import "../../libs/LibMath.sol"; import "../TaikoData.sol"; /// @title LibUtils /// @notice A library that offers helper functions. /// @custom:security-contact [email protected] library LibUtils { using LibMath for uint256; // Warning: Any errors defined here must also be defined in TaikoErrors.sol. error L1_BLOCK_MISMATCH(); error L1_INVALID_BLOCK_ID(); error L1_TRANSITION_NOT_FOUND(); error L1_UNEXPECTED_TRANSITION_ID(); /// @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 data of the block. function getTransition( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId, bytes32 _parentHash ) internal view returns (TaikoData.TransitionState storage) { _checkBlockId(_state, _blockId); (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]; } /// @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 data of the block. function getTransition( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId, uint32 _tid ) internal view returns (TaikoData.TransitionState storage) { _checkBlockId(_state, _blockId); (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]; } /// @dev Retrieves a block based on its ID. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. 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 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; } else { tid_ = _state.transitionIds[_blk.blockId][_parentHash]; } if (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 _checkBlockId(TaikoData.State storage _state, uint64 _blockId) private view { TaikoData.SlotB memory b = _state.slotB; if (_blockId < b.lastVerifiedBlockId || _blockId >= b.numBlocks) { revert L1_INVALID_BLOCK_ID(); } } }
// 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 authrized True if authorized, false otherwise. event Authorized(address indexed addr, bool authrized); /// @notice Send a signal (message) by setting the storage slot to a value of 1. /// @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. /// 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 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. uint64 maxBlocksToVerifyPerProposal; // 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 max number of L2 blocks that can stay unsynced on L1 (a value of zero disables // syncing) uint8 blockSyncThreshold; } /// @dev Struct representing prover fees per given tier struct TierFee { uint16 tier; uint128 fee; } /// @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; address coinbase; bytes32 extraData; bytes32 parentMetaHash; HookCall[] hookCalls; 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. /// 10 slots reserved for upgradability, 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; 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 uint256[44] __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 // 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.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// 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 // 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/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"ETH_TRANSFER_FAILED","type":"error"},{"inputs":[],"name":"INVALID_PAUSE_STATUS","type":"error"},{"inputs":[],"name":"L1_ALREADY_CONTESTED","type":"error"},{"inputs":[],"name":"L1_ALREADY_CONTESTED","type":"error"},{"inputs":[],"name":"L1_ALREADY_PROVED","type":"error"},{"inputs":[],"name":"L1_ALREADY_PROVED","type":"error"},{"inputs":[],"name":"L1_BLOB_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"L1_BLOB_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"L1_BLOB_NOT_FOUND","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_BLOCK_MISMATCH","type":"error"},{"inputs":[],"name":"L1_CANNOT_CONTEST","type":"error"},{"inputs":[],"name":"L1_CANNOT_CONTEST","type":"error"},{"inputs":[],"name":"L1_INVALID_BLOCK_ID","type":"error"},{"inputs":[],"name":"L1_INVALID_BLOCK_ID","type":"error"},{"inputs":[],"name":"L1_INVALID_BLOCK_ID","type":"error"},{"inputs":[],"name":"L1_INVALID_CONFIG","type":"error"},{"inputs":[],"name":"L1_INVALID_CONFIG","type":"error"},{"inputs":[],"name":"L1_INVALID_GENESIS_HASH","type":"error"},{"inputs":[],"name":"L1_INVALID_GENESIS_HASH","type":"error"},{"inputs":[],"name":"L1_INVALID_HOOK","type":"error"},{"inputs":[],"name":"L1_INVALID_HOOK","type":"error"},{"inputs":[],"name":"L1_INVALID_PARAM","type":"error"},{"inputs":[],"name":"L1_INVALID_PAUSE_STATUS","type":"error"},{"inputs":[],"name":"L1_INVALID_PAUSE_STATUS","type":"error"},{"inputs":[],"name":"L1_INVALID_PROVER","type":"error"},{"inputs":[],"name":"L1_INVALID_PROVER","type":"error"},{"inputs":[],"name":"L1_INVALID_SIG","type":"error"},{"inputs":[],"name":"L1_INVALID_SIG","type":"error"},{"inputs":[],"name":"L1_INVALID_TIER","type":"error"},{"inputs":[],"name":"L1_INVALID_TIER","type":"error"},{"inputs":[],"name":"L1_INVALID_TRANSITION","type":"error"},{"inputs":[],"name":"L1_INVALID_TRANSITION","type":"error"},{"inputs":[],"name":"L1_LIVENESS_BOND_NOT_RECEIVED","type":"error"},{"inputs":[],"name":"L1_LIVENESS_BOND_NOT_RECEIVED","type":"error"},{"inputs":[],"name":"L1_NOT_ASSIGNED_PROVER","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_TOO_MANY_BLOCKS","type":"error"},{"inputs":[],"name":"L1_TRANSITION_ID_ZERO","type":"error"},{"inputs":[],"name":"L1_TRANSITION_ID_ZERO","type":"error"},{"inputs":[],"name":"L1_TRANSITION_NOT_FOUND","type":"error"},{"inputs":[],"name":"L1_TRANSITION_NOT_FOUND","type":"error"},{"inputs":[],"name":"L1_UNAUTHORIZED","type":"error"},{"inputs":[],"name":"L1_UNAUTHORIZED","type":"error"},{"inputs":[],"name":"L1_UNEXPECTED_PARENT","type":"error"},{"inputs":[],"name":"L1_UNEXPECTED_PARENT","type":"error"},{"inputs":[],"name":"L1_UNEXPECTED_TRANSITION_ID","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_ADDR_MANAGER","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":"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":"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":[{"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":"deposit","type":"tuple"}],"name":"EthDeposited","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":[{"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":[{"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":"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":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":"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":"maxBlocksToVerifyPerProposal","type":"uint64"},{"internalType":"uint32","name":"blockMaxGasLimit","type":"uint32"},{"internalType":"uint96","name":"livenessBond","type":"uint96"},{"internalType":"uint8","name":"blockSyncThreshold","type":"uint8"}],"internalType":"struct TaikoData.Config","name":"","type":"tuple"}],"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":"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":"slotA","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"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"slotB","outputs":[{"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":[],"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"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523060805234801562000014575f80fd5b506200001f6200002f565b620000296200002f565b620000ed565b5f54610100900460ff16156200009b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614620000eb575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615cbe620001225f395f8181610aa901528181610ae901528181610bc701528181610c070152610c980152615cbe5ff3fe6080604052600436106101bd575f3560e01c806379ba5097116100f2578063c782156811610092578063ef16e84511610062578063ef16e845146106b8578063f2fde38b146106d9578063fd257e29146106f8578063ff00c39114610717575f80fd5b8063c7821568146105b2578063dde89cf51461063c578063e07baba61461065e578063e30c39781461069b575f80fd5b80638da5cb5b116100cd5780638da5cb5b1461040a578063a86f9d9e14610427578063c19d93fb14610446578063c3f909d414610526575f80fd5b806379ba5097146103c35780638456cb59146103d75780638778209d146103eb575f80fd5b80633f4ba83a1161015d578063563479a511610138578063563479a5146103275780635c975abb146103535780635fa15e7914610383578063715018a6146103af575f80fd5b80633f4ba83a146102de5780634f1ef286146102f257806352d1902d14610305575f80fd5b806329d1b62f1161019857806329d1b62f1461024a5780633659cfe6146102695780633ab76e9f146102885780633eb6b8cf146102bf575f80fd5b8063069489a2146101ed57806310d008bd1461020157806319e8dce214610220575f80fd5b366101e9576101ca610736565b6101e757604051630d28633960e01b815260040160405180910390fd5b005b5f80fd5b3480156101f8575f80fd5b506101e761074a565b34801561020c575f80fd5b506101e761021b366004614b76565b610802565b34801561022b575f80fd5b5061023461092b565b6040516102419190614c28565b60405180910390f35b348015610255575f80fd5b506101e7610264366004614c6d565b6109b4565b348015610274575f80fd5b506101e7610283366004614cbd565b610a9f565b348015610293575f80fd5b506097546102a7906001600160a01b031681565b6040516001600160a01b039091168152602001610241565b3480156102ca575f80fd5b506102a76102d9366004614cd8565b610b7c565b3480156102e9575f80fd5b506101e7610b92565b6101e7610300366004614e33565b610bbd565b348015610310575f80fd5b50610319610c8c565b604051908152602001610241565b348015610332575f80fd5b50610346610341366004614e92565b610d3d565b6040516102419190614ec5565b34801561035e575f80fd5b5061037360c954610100900460ff1660021490565b6040519015158152602001610241565b34801561038e575f80fd5b506103a261039d366004614f90565b610e01565b604051610241919061502a565b3480156103ba575f80fd5b506101e7610ee8565b3480156103ce575f80fd5b506101e7610efb565b3480156103e2575f80fd5b506101e7610f72565b3480156103f6575f80fd5b506101e7610405366004614f90565b610f85565b348015610415575f80fd5b506033546001600160a01b03166102a7565b348015610432575f80fd5b506102a7610441366004615039565b611040565b348015610451575f80fd5b5060fe54604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c0830152610517929183565b6040516102419392919061509a565b348015610531575f80fd5b5061053a61104c565b60405161024191905f60e0820190506001600160401b038084511683528060208501511660208401528060408501511660408401528060608501511660608401525063ffffffff60808401511660808301526001600160601b0360a08401511660a083015260ff60c08401511660c083015292915050565b3480156105bd575f80fd5b5061062f604080516080810182525f808252602082018190529181018290526060810191909152506040805160808101825260ff546001600160401b038082168352600160401b820481166020840152600160801b8204811693830193909352600160c01b9004909116606082015290565b60405161024191906150bc565b348015610647575f80fd5b506106506110d3565b6040516102419291906150ca565b348015610669575f80fd5b5060c954610683906201000090046001600160401b031681565b6040516001600160401b039091168152602001610241565b3480156106a6575f80fd5b506065546001600160a01b03166102a7565b6106cb6106c63660046150e6565b6111bd565b604051610241929190615299565b3480156106e4575f80fd5b506101e76106f3366004614cbd565b611291565b348015610703575f80fd5b506103466107123660046152c3565b611302565b348015610722575f80fd5b506101e76107313660046152ed565b61131e565b5f6002610741611333565b60ff1614905090565b610752611372565b5f54600290610100900460ff1615801561077257505f5460ff8083169116105b6107975760405162461bcd60e51b815260040161078e90615308565b60405180910390fd5b5f8054610100805466ffffffffffffff60881b1916815560fe83905561ff001960ff851661ffff199093168317909117169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b61081660c954610100900460ff1660021490565b156108345760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610860576040516333018e5560e11b815260040160405180910390fd5b600261086a611333565b60ff160361088b5760405163dfc60d8560e01b815260040160405180910390fd5b61089560026113cc565b5f80806108a48486018661542a565b9250925092508260c001516001600160401b0316866001600160401b0316146108e057604051638a1c400f60e01b815260040160405180910390fd5b5f6108e961104c565b90505f6108fb60fb8330888888611414565b905061090d60fb83308460ff16611de6565b505050505061091c60fb61235c565b61092660016113cc565b505050565b61093361497e565b506040805160e081018252610100546001600160401b038082168352600160401b82048116602084015260ff600160801b83048116151594840194909452600160881b8204909316606083015261ffff600160901b820416608083015263ffffffff600160a01b82041660a0830152600160c01b900490911660c082015290565b5f54610100900460ff16158080156109d257505f54600160ff909116105b806109eb5750303b1580156109eb57505f5460ff166001145b610a075760405162461bcd60e51b815260040161078e90615308565b5f805460ff191660011790558015610a28575f805461ff0019166101001790555b610a3285856123f1565b610a4560fb610a3f61104c565b85612450565b8115610a5357610a536125c8565b8015610a98575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610ae75760405162461bcd60e51b815260040161078e9061555e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b2f5f80516020615c42833981519152546001600160a01b031690565b6001600160a01b031614610b555760405162461bcd60e51b815260040161078e906155aa565b610b5e8161263f565b604080515f80825260208201909252610b7991839190612647565b50565b5f610b888484846127b1565b90505b9392505050565b610b9a6128a2565b61010080546001600160c01b0316600160c01b426001600160401b031602179055565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610c055760405162461bcd60e51b815260040161078e9061555e565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610c4d5f80516020615c42833981519152546001600160a01b031690565b6001600160a01b031614610c735760405162461bcd60e51b815260040161078e906155aa565b610c7c8261263f565b610c8882826001612647565b5050565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d2b5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161078e565b505f80516020615c4283398151915290565b610d456149b9565b610d5960fb610d5261104c565b85856128b4565b6040805161014081018252825481526001830154602082015260028301549181019190915260038201546001600160a01b0380821660608401526001600160601b03600160a01b9283900481166080850152600485015491821660a08501529190041660c08201526005909101546001600160401b03811660e083015261ffff600160401b82041661010083015260ff600160501b9091041661012082015290505b92915050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152610e5460fb610e4e61104c565b8461294c565b5060408051610100810182528254815260018301546001600160a01b03811660208301526001600160601b03600160a01b90910416918101919091526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b82041660a083015263ffffffff600160c01b8204811660c0840152600160e01b9091041660e082015292915050565b610ef0611372565b610ef95f6129ac565b565b60655433906001600160a01b03168114610f695760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161078e565b610b79816129ac565b610f7a6125c8565b610ef93360016129c5565b610f9960c954610100900460ff1660021490565b15610fb75760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610fe3576040516333018e5560e11b815260040160405180910390fd5b6002610fed611333565b60ff160361100e5760405163dfc60d8560e01b815260040160405180910390fd5b61101860026113cc565b61102c60fb61102561104c565b3084611de6565b61103660fb61235c565b610b7960016113cc565b5f610b8b4684846127b1565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152506040805160e08101825262028c588152622dc6c06020820152622dedd091810191909152600a6060820152630e4e1c006080820152680d8d726b7177a8000060a0820152601060c082015290565b604080516080810182525f8082526020820181905291810182905260608101919091526110fe61497e565b5050604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015291565b6111c5614a0c565b60606111db60c954610100900460ff1660021490565b156111f95760405163bae6e2a960e01b815260040160405180910390fd5b6002611203611333565b60ff16036112245760405163dfc60d8560e01b815260040160405180910390fd5b61122e60026113cc565b5f61123761104c565b905061124b60fb82308a8a8a8a6001612a44565b610100549194509250600160801b900460ff166112735761127360fb82308460600151611de6565b5061127e60fb61235c565b61128860016113cc565b94509492505050565b611299611372565b606580546001600160a01b0383166001600160a01b031990911681179091556112ca6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61130a6149b9565b610d5960fb61131761104c565b85856134fb565b61132833826129c5565b610b7960fb82613582565b5f61133d4661362f565b1561136857507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b6033546001600160a01b03163314610ef95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078e565b6113d54661362f565b1561140057807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b81515f90158061142657506020830151155b8061143357506040830151155b15611451576040516317eddea160e11b815260040160405180910390fd5b611459614a7f565b6040805160e08101825260058a01546001600160401b038082168352600160401b820481166020840190815260ff600160801b84048116151595850195909552600160881b8304909416606084015261ffff600160901b830416608084015263ffffffff600160a01b83041660a0840152600160c01b909104811660c080840191909152918452915190870151908216911611158061150b575080515160c08601516001600160401b03918216911610155b1561152957604051638a1c400f60e01b815260040160405180910390fd5b86604001518560c0015161153d919061560a565b6001600160401b0390811660a083018190525f90815260208a90526040908190206002810154831660c080860182905260018301546001600160a01b03166060870152825493860193909352918801519092161415806115c75750856040516020016115a9919061563b565b60405160208183030381529060405280519060200120826040015114155b156115e557604051632ec3485560e11b815260040160405180910390fd5b5f6115f28a83888661365c565b63ffffffff90911660e0850152855190915061ffff161580611623575086610140015161ffff16855f015161ffff16105b8061164157506005810154855161ffff600160401b90920482169116105b1561165f57604051631a32f51360e01b815260040160405180910390fd5b604051635437cecf60e11b81526c3a34b2b92fb83937bb34b232b960991b60048201525f60248201526001600160a01b0389169063a86f9d9e90604401602060405180830381865afa1580156116b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116db919061564a565b855160405163576c3de760e01b815261ffff90911660048201526001600160a01b03919091169063576c3de79060240160c060405180830381865afa158015611726573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061174a919061567b565b602084018190526005820154845160c0015160809092015161177d926001600160401b0392831692169061ffff166137e9565b156101408401526020830151604001516001600160601b0316158015906117af575060048101546001600160a01b0316155b80156117c557508260e0015163ffffffff166001145b80156117de57506005810154600160401b900461ffff16155b80156117ec57508261014001515b156118275782606001516001600160a01b0316336001600160a01b03161461182757604051632185a2ad60e21b815260040160405180910390fd5b6020830151511561199157602083015151604051635437cecf60e11b815260048101919091525f60248201819052906001600160a01b038a169063a86f9d9e90604401602060405180830381865afa158015611885573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118a9919061564a565b600583015487519192505f9161ffff908116600160401b909204161480156118e157506020850151604001516001600160601b031615155b6040805160e0810182528782015181528b82015160208201523381830181905260c0808a01516001600160401b0316606084015284151560808401526101608e0151151560a0840152820152905163043d132d60e31b8152919250906001600160a01b038416906321e89968906119609084908d908d90600401615774565b5f604051808303815f87803b158015611977575f80fd5b505af1158015611989573d5f803e3d5ffd5b505050505050505b60208301516040908101516001600160601b03161561012085015251635437cecf60e11b81526a3a30b4b5b7afba37b5b2b760a91b60048201525f60248201819052906001600160a01b038a169063a86f9d9e90604401602060405180830381865afa158015611a03573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a27919061564a565b6001840154600160a01b90046001600160601b0316608086015261012085015190915015611af35760808401516001600160601b031615611af35783610140015180611aaf57508560200151516020148015611aaf57507f20d34d7a20a139f9be221ba2163925c0c86ed02d34033f288f010d23a63ef4b78660200151611aad9061580c565b145b15611adb5760608401516080850151611adb916001600160a01b038416916001600160601b0316613806565b6001830180546001600160a01b031690555f60808501525b81600101548760200151148015611b11575081600201548760400151145b15156101608501526005820154865161ffff600160401b909204821691161115611b9e57611b43838389898886613869565b8360c001516001600160401b03167fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f88338760200151602001518a5f0151604051611b919493929190615832565b60405180910390a2611db4565b83610160015115611bc257604051639d49773160e01b815260040160405180910390fd5b83610120015115611c955760208085015101516001600160601b031615611beb57611beb615885565b6003820154600160a01b90046001600160601b0316158015611c18575060048201546001600160a01b0316155b611c2457611c24615885565b6003820180546001600160a01b0319163390811790915560208801516001840155604080890151600285015560c0860151885191516001600160401b03909116927fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f92611b91928c92915f91615832565b60048201546001600160a01b031615611cc1576040516382ef169960e01b815260040160405180910390fd5b6005820154845160c00151602086015160600151611cf1926001600160401b0390811692169062ffffff166137e9565b15611d0f5760405163378b1eff60e21b815260040160405180910390fd5b602084015160400151611d39906001600160a01b03831690339030906001600160601b0316613b07565b6020840151604090810151336001600160a01b0319600160a01b6001600160601b03841602168117600486015560c0870151895193516001600160401b03909116937fb4c0a86c1ff239277697775b1e91d3375fd3a5ef6b345aa4e2f6001c890558f693611dab938d93909290615832565b60405180910390a25b50600501805467ffffffffffffffff1916426001600160401b0316179055506020015160a00151979650505050505050565b6001600160401b03811615612356576040805160e08101825260058601546001600160401b038082168352600160401b820481166020840181905260ff600160801b84048116151585870152600160881b840416606085015261ffff600160901b840416608085015263ffffffff600160a01b84041660a0850152600160c01b9092041660c0830152918501519091905f90611e82908361560a565b6001600160401b038082165f90815260208a905260409020600281015492935091811690841614611ec657604051632ec3485560e11b815260040160405180910390fd5b6002810154600160e01b900463ffffffff165f819003611ef95760405163d4345b9760e01b815260040160405180910390fd5b6001600160401b0383165f90815260028a016020908152604080832063ffffffff85168452909152808220600101549051635437cecf60e11b81526a3a30b4b5b7afba37b5b2b760a91b6004820152602481018390529091908190819081906001600160a01b038d169063a86f9d9e90604401602060405180830381865afa158015611f87573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fab919061564a565b90508860010198505b895f01516001600160401b0316896001600160401b0316108015611fe957508a6001600160401b0316836001600160401b0316105b156122f6578c604001516001600160401b0316896001600160401b031681612013576120136155f6565b0697508d5f015f896001600160401b03166001600160401b031681526020019081526020015f209650886001600160401b0316876002015f9054906101000a90046001600160401b03166001600160401b03161461208457604051632ec3485560e11b815260040160405180910390fd5b6120908e888a88613b3f565b955063ffffffff8616156122f6576001600160401b0388165f90815260028f016020908152604080832063ffffffff8a168452909152902060048101546001600160a01b0316156120e157506122f6565b6001600160a01b03831661216e57604051635437cecf60e11b81526c3a34b2b92fb83937bb34b232b960991b60048201525f60248201526001600160a01b038e169063a86f9d9e90604401602060405180830381865afa158015612147573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216b919061564a565b92505b600581015460c08c015160405163576c3de760e01b8152600160401b830461ffff166004820152612208926001600160401b039081169216906001600160a01b0387169063576c3de79060240160c060405180830381865afa1580156121d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fa919061567b565b6060015162ffffff166137e9565b61221257506122f6565b6002808901805463ffffffff808b16600160e01b026001600160e01b039092169190911790915560018301549183015460038401549298509650612278916001600160a01b0385811692908216916001600160601b03600160a01b909104169061380616565b600381015460058201546040805189815260208101899052600160401b90920461ffff16908201526001600160a01b03909116906001600160401b038c16907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a389600101995083600101935050611fb4565b6001600160401b0383161561234b5760208a015160058f0180546001600160401b03928601928316600160401b026fffffffffffffffff0000000000000000199091161790556123498f8f8f8489613bda565b505b505050505050505050505b50505050565b7fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b816005016040516107f791905f60e08201905082546001600160401b038082168452808260401c1660208501525060ff8160801c161515604084015260ff8160881c16606084015261ffff8160901c16608084015263ffffffff8160a01c1660a08401528060c01c60c08401525092915050565b5f54610100900460ff166124175760405162461bcd60e51b815260040161078e90615899565b6001600160a01b03811661243e576040516375cabfef60e11b815260040160405180910390fd5b61244782613e19565b610c8881613e49565b61245982613eb9565b6124765760405163223aca4d60e21b815260040160405180910390fd5b5f8190036124975760405163d6d0f75560e01b815260040160405180910390fd5b600483018054426001600160401b03908116600160401b81026fffffffffffffffffffffffffffffffff1990931643929092169190911782179092556005808601805467ffffffffffffffff1990811660019081179092555f80805260208981526040808320600280820180546001600160e01b037fffffffff00000000ffffffffffffffff0000000000000000ffffffffffffffff909116909a17600160c11b1799909916600160e01b17909855858155968b01825280832085845282528083209485018990556003850180546001600160a01b031916905594840180549093169096179091558251868152948501819052918401829052919281907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a35050505050565b6125dc60c954610100900460ff1660021490565b156125fa5760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b610b79611372565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561267a5761092683613f65565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156126d4575060408051601f3d908101601f191682019092526126d1918101906158e4565b60015b6127375760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161078e565b5f80516020615c4283398151915281146127a55760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161078e565b50610926838383614000565b6097545f906001600160a01b0316806127dd57604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0386166004820152602481018590526001600160a01b038216906328f713cc90604401602060405180830381865afa15801561282f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612853919061564a565b91508215801561286a57506001600160a01b038216155b1561289a57604051632b0d65db60e01b81526001600160401b03861660048201526024810185905260440161078e565b509392505050565b6128aa614024565b610ef9335f6129c5565b5f6128bf85846140ae565b5f806128cc87878761294c565b915091508363ffffffff165f14806128f95750600282015463ffffffff600160c01b909104811690851610155b156129175760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b03165f908152600287016020908152604080832063ffffffff8716845290915290209150505b949350505050565b5f8083604001518361295e919061560a565b6001600160401b038181165f90815260208890526040902060028101549094509192508481169116146129a457604051638a1c400f60e01b815260040160405180910390fd5b935093915050565b606580546001600160a01b0319169055610b7981614172565b6d636861696e5f7761746368646f6760901b6129e96033546001600160a01b031690565b6001600160a01b0316336001600160a01b031614158015612a265750612a10816001611040565b6001600160a01b0316336001600160a01b031614155b1561092657604051630d85cccf60e11b815260040160405180910390fd5b612a4c614a0c565b60605f612a5b878901896159d7565b80519091506001600160a01b0316612a865760405163041bee0760e41b815260040160405180910390fd5b60208101516001600160a01b0316612a9f573360208201525b6040805160e08101825260058d01546001600160401b038082168352600160401b82048116602084015260ff600160801b83048116151594840194909452600160881b8204909316606083015261ffff600160901b820416608083015263ffffffff600160a01b82041660a0830152600160c01b900490911660c0820152612b27818b6141c3565b612b4457604051631231017d60e01b815260040160405180910390fd5b8a602001518160200151612b589190615aab565b612b63906001615aab565b6001600160401b0316815f01516001600160401b031610612b97576040516351ec7d5360e01b815260040160405180910390fd5b5f8c5f015f8d604001516001855f0151612bb19190615ad2565b612bbb919061560a565b6001600160401b0316815260208101919091526040015f2054606084015190915015801590612bee575082606001518114155b15612c0c57604051630d41ec8760e11b815260040160405180910390fd5b604051806101c00160405280600143034081526020015f801b81526020015f801b8152602001846040015181526020017f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd5f1b815260200184602001516001600160a01b03168152602001835f01516001600160401b031681526020018d6080015163ffffffff168152602001426001600160401b03168152602001600143036001600160401b031681526020015f61ffff168152602001898990505f1415158152602001828152602001336001600160a01b0316815250945084610160015115612d4557612cfa4661362f565b612d175760405163df9969ef60e01b815260040160405180910390fd5b5f8049604087018190529003612d4057604051639e7e2ddd60e01b815260040160405180910390fd5b612dcc565b8787604051612d55929190615af2565b604080519182900390912090860152858015612d7f57508460c001516001600160401b0316600114155b8015612dae5750336001600160a01b0316612da286604001518560a00151614319565b6001600160a01b031614155b15612dcc5760405163f6ee3bdb60e01b815260040160405180910390fd5b81516040805144602082015260c09290921b6001600160c01b0319169082015243604882015260680160408051808303601f1901815291815281516020928301209187019190915251635437cecf60e11b81526c3a34b2b92fb83937bb34b232b960991b60048201525f60248201526001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015612e6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e8e919061564a565b60208601516040516359ab4e2360e01b81526001600160a01b0392909216916359ab4e2391612ec39160040190815260200190565b602060405180830381865afa158015612ede573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f029190615b01565b61ffff166101408601526040805161010081019091525f9080612f2988610120830161563b565b604051602081830303815290604052805190602001208152602001855f01516001600160a01b031681526020018e60a001516001600160601b03168152602001845f01516001600160401b031681526020018761010001516001600160401b03168152602001436001600160401b03168152602001600163ffffffff1681526020015f63ffffffff168152509050808e5f015f8f60400151865f0151612fcf919061560a565b6001600160401b03166001600160401b031681526020019081526020015f205f820151815f01556020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160601b0302191690836001600160601b031602179055506060820151816002015f6101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160020160086101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160020160106101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160020160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600201601c6101000a81548163ffffffff021916908363ffffffff1602179055509050508d6005015f015f81819054906101000a90046001600160401b031660010191906101000a8154816001600160401b0302191690836001600160401b031602179055505f8c6001600160a01b031663a86f9d9e6a3a30b4b5b7afba37b5b2b760a91b5f6040518363ffffffff1660e01b81526004016131b09291909182521515602082015260400190565b602060405180830381865afa1580156131cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ef919061564a565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa158015613236573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061325a91906158e4565b90505f805b87608001515181101561338a578760800151818151811061328257613282615b1c565b60200260200101515f01516001600160a01b0316826001600160a01b0316106132be5760405163390ed16960e21b815260040160405180910390fd5b876080015181815181106132d4576132d4615b1c565b60200260200101515f01516001600160a01b03166336b6ea4e47878d8c60800151868151811061330657613306615b1c565b6020026020010151602001516040518563ffffffff1660e01b815260040161333093929190615b30565b5f604051808303818588803b158015613347575f80fd5b505af1158015613359573d5f803e3d5ffd5b50505050508760800151818151811061337457613374615b1c565b602090810291909101015151915060010161325f565b50471561339b5761339b3347614333565b8f60a001516001600160601b0316826133b49190615b5f565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156133f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061341a91906158e4565b1461343857604051631bf37e2160e11b815260040160405180910390fd5b505f91506134439050565b60405190808252806020026020018201604052801561348c57816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816134615790505b50945080602001516001600160a01b031681606001516001600160401b03167fcda4e564245eb15494bc6da29f6a42e1941cf57f5314bf35bab8a1fca0a9c60a8f60a0015189896040516134e293929190615b72565b60405180910390a3505050509850989650505050505050565b5f61350685846140ae565b5f8061351387878761294c565b915091505f61352488848488613b3f565b90508063ffffffff165f0361354c5760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b039091165f908152600288016020908152604080832063ffffffff909416835292905220915050949350505050565b6005820154811515600160801b90910460ff161515036135b55760405163689d009d60e11b815260040160405180910390fd5b60058201805460ff60801b1916600160801b83151502179055806135f6576005820180546001600160c01b0316600160c01b426001600160401b0316021790555b60405181151581527fed64db85835d07c3c990b8ebdd55e32d64e5ed53143b6ef2179e7bfaf17ddc3b9060200160405180910390a15050565b5f6001821480613640575061426882145b8061364d575062aa36a782145b80610dfb5750610dfb8261433e565b5f8061367186868560a00151875f0151613b3f565b91508163ffffffff165f036137b157505060028084018054600163ffffffff600160c01b80840482168381019092160263ffffffff60c01b1990931692909217835560a08501516001600160401b039081165f908152898601602090815260408083208684529091528120808401829055958601556003850180546001600160a01b03169055600160a01b600486015592546005850180546affffffffffffffffffffff1916600160401b90920490941617909255919082900361375e578351815560608301516003820180546001600160a01b0319166001600160a01b03909216919091179055611288565b6003810180546001600160a01b031916905560c08301516001600160401b03165f9081526001870160209081526040808320875184529091529020805463ffffffff191663ffffffff8416179055611288565b5060a08201516001600160401b03165f908152600286016020908152604080832063ffffffff85168452909152902094509492505050565b5f80603c83026137f98686614355565b0142101595945050505050565b6040516001600160a01b03831660248201526044810182905261092690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261436a565b60048501545f906001600160a01b03161561394f57826101600151156138dd5760048601546138a790600160a01b90046001600160601b031661443d565b60038701549091506138d8906001600160a01b038481169190811690600160a01b90046001600160601b0316613806565b6139f2565b60038601546002906138fe90600160a01b90046001600160601b031661443d565b6004880154911c91506138d8906001600160a01b031661391f836003615ba2565b600489015461393e9190600160a01b90046001600160601b0316615b5f565b6001600160a01b0385169190613806565b8261016001511561397357604051639d49773160e01b815260040160405180910390fd5b600386015461399190600160a01b90046001600160601b031661443d565b905082608001516001600160601b03165f146139f25760608301516001600160a01b0316331480156139c557508261014001515b156139da5760808301516001600160601b0316015b6001870180546001600160a01b031690555f60808401525b8260200151602001516001600160601b0316811115613a39576020808401510151613a34906001600160a01b0384169033906001600160601b03168403613806565b613a85565b8260200151602001516001600160601b0316811015613a8557613a853330838660200151602001516001600160601b031603856001600160a01b0316613b07909392919063ffffffff16565b6020808401510151600160a01b600488018190556001600160601b03909116026001600160a01b03191633176003870155835160058701805461ffff909216600160401b0269ffff000000000000000019909216919091179055610160830151613afe5760208501516001870155604085015160028701555b50505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526123569085906323b872dd60e01b90608401613832565b6001600160401b0382165f908152600285016020908152604080832060018452909152812054829003613b7457506001613ba5565b5060028301546001600160401b03165f908152600185016020908152604080832084845290915290205463ffffffff165b600284015463ffffffff600160c01b909104811690821610612944576040516367a1907f60e01b815260040160405180910390fd5b604051635437cecf60e11b81526d7369676e616c5f7365727669636560901b60048201525f60248201819052906001600160a01b0385169063a86f9d9e90604401602060405180830381865afa158015613c36573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c5a919061564a565b855160405163dfc8ff1d60e01b81526001600160401b0390911660048201527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da16960248201525f604482018190529192506001600160a01b0383169063dfc8ff1d906064016040805180830381865afa158015613cd8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613cfc9190615bb9565b5090508560c0015160ff1681613d129190615aab565b6001600160401b0316846001600160401b03161115613afe57600487810180546fffffffffffffffffffffffffffffffff16600160801b6001600160401b038881169182026001600160c01b031692909217600160c01b428416021790925588516040516313e4299d60e21b81529116928101929092527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da16960248301526044820152606481018490526001600160a01b03831690634f90a674906084016020604051808303815f875af1158015613deb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e0f91906158e4565b5050505050505050565b613e376001600160a01b03821615613e3157816129ac565b336129ac565b5060c9805461ff001916610100179055565b5f54610100900460ff16613e6f5760405162461bcd60e51b815260040161078e90615899565b6001600160401b03461115613e975760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b5f6001825f01516001600160401b0316111580613edf575081516001600160401b031646145b80613ef85750600182602001516001600160401b031611155b80613f2857506020820151613f0e906001615aab565b6001600160401b031682604001516001600160401b031611155b80613f3b5750608082015163ffffffff16155b80613f51575060a08201516001600160601b0316155b15613f5d57505f919050565b506001919050565b6001600160a01b0381163b613fd25760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161078e565b5f80516020615c4283398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6140098361445f565b5f825111806140155750805b1561092657612356838361449e565b61403860c954610100900460ff1660021490565b6140555760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001612635565b6040805160e08101825260058401546001600160401b038082168352600160401b820481166020840181905260ff600160801b84048116151595850195909552600160881b8304909416606084015261ffff600160901b830416608084015263ffffffff600160a01b83041660a0840152600160c01b909104811660c0830152909190831610806141545750805f01516001600160401b0316826001600160401b031610155b1561092657604051638a1c400f60e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b81515f906001600160401b031660010361427a57604051635437cecf60e11b81526b70726f706f7365725f6f6e6560a01b6004820152600160248201525f906001600160a01b0384169063a86f9d9e90604401602060405180830381865afa158015614231573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614255919061564a565b90506001600160a01b03811615614278576001600160a01b031633149050610dfb565b505b604051635437cecf60e11b815267383937b837b9b2b960c11b6004820152600160248201525f906001600160a01b0384169063a86f9d9e90604401602060405180830381865afa1580156142d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906142f4919061564a565b90506001600160a01b038116158061294457506001600160a01b031633149392505050565b5f805f61432685856144c3565b9150915061289a81614505565b610c8882825a61464e565b5f617e2c8210158015610dfb575050617e90101590565b5f8183116143635781610b8b565b5090919050565b5f6143be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146919092919063ffffffff16565b905080515f14806143de5750808060200190518101906143de9190615be5565b6109265760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161078e565b5f8115614458576003614451836007615ba2565b901c610dfb565b5f92915050565b61446881613f65565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b8b8383604051806060016040528060278152602001615c626027913961469f565b5f8082516041036144f7576020830151604084015160608501515f1a6144eb87828585614713565b945094505050506144fe565b505f905060025b9250929050565b5f81600481111561451857614518615c00565b036145205750565b600181600481111561453457614534615c00565b036145815760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161078e565b600281600481111561459557614595615c00565b036145e25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161078e565b60038160048111156145f6576145f6615c00565b03610b795760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161078e565b815f0361465a57505050565b61467483838360405180602001604052805f8152506147cd565b61092657604051634c67134d60e11b815260040160405180910390fd5b6060610b8884845f8561480a565b60605f80856001600160a01b0316856040516146bb9190615c14565b5f60405180830381855af49150503d805f81146146f3576040519150601f19603f3d011682016040523d82523d5f602084013e6146f8565b606091505b5091509150614709868383876148e1565b9695505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561474857505f90506003611288565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614799573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166147c1575f60019250925050611288565b965f9650945050505050565b5f6001600160a01b0385166147f557604051634c67134d60e11b815260040160405180910390fd5b5f80835160208501878988f195945050505050565b60608247101561486b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161078e565b5f80866001600160a01b031685876040516148869190615c14565b5f6040518083038185875af1925050503d805f81146148c0576040519150601f19603f3d011682016040523d82523d5f602084013e6148c5565b606091505b50915091506148d6878383876148e1565b979650505050505050565b6060831561494f5782515f03614948576001600160a01b0385163b6149485760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161078e565b5081612944565b61294483838151156149645781518083602001fd5b8060405162461bcd60e51b815260040161078e9190615c2f565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b604080516101c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b604051806101800160405280614a9361497e565b81526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b6001600160401b0381168114610b79575f80fd5b8035614b3481614b15565b919050565b5f8083601f840112614b49575f80fd5b5081356001600160401b03811115614b5f575f80fd5b6020830191508360208285010111156144fe575f80fd5b5f805f60408486031215614b88575f80fd5b8335614b9381614b15565b925060208401356001600160401b03811115614bad575f80fd5b614bb986828701614b39565b9497909650939450505050565b6001600160401b0380825116835280602083015116602084015260408201511515604084015260ff606083015116606084015261ffff608083015116608084015263ffffffff60a08301511660a08401528060c08301511660c0840152505050565b60e08101610dfb8284614bc6565b6001600160a01b0381168114610b79575f80fd5b8035614b3481614c36565b8015158114610b79575f80fd5b8035614b3481614c55565b5f805f8060808587031215614c80575f80fd5b8435614c8b81614c36565b93506020850135614c9b81614c36565b9250604085013591506060850135614cb281614c55565b939692955090935050565b5f60208284031215614ccd575f80fd5b8135610b8b81614c36565b5f805f60608486031215614cea575f80fd5b8335614cf581614b15565b9250602084013591506040840135614d0c81614c55565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715614d4d57614d4d614d17565b60405290565b6040516101c081016001600160401b0381118282101715614d4d57614d4d614d17565b60405160c081016001600160401b0381118282101715614d4d57614d4d614d17565b604051601f8201601f191681016001600160401b0381118282101715614dc057614dc0614d17565b604052919050565b5f82601f830112614dd7575f80fd5b81356001600160401b03811115614df057614df0614d17565b614e03601f8201601f1916602001614d98565b818152846020838601011115614e17575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614e44575f80fd5b8235614e4f81614c36565b915060208301356001600160401b03811115614e69575f80fd5b614e7585828601614dc8565b9150509250929050565b803563ffffffff81168114614b34575f80fd5b5f8060408385031215614ea3575f80fd5b8235614eae81614b15565b9150614ebc60208401614e7f565b90509250929050565b5f610140820190508251825260208301516020830152604083015160408301526060830151614eff60608401826001600160a01b03169052565b506080830151614f1a60808401826001600160601b03169052565b5060a0830151614f3560a08401826001600160a01b03169052565b5060c0830151614f5060c08401826001600160601b03169052565b5060e0830151614f6b60e08401826001600160401b03169052565b506101008381015161ffff16908301526101209283015160ff16929091019190915290565b5f60208284031215614fa0575f80fd5b8135610b8b81614b15565b8051825260018060a01b0360208201511660208301526001600160601b03604082015116604083015260608101516001600160401b0380821660608501528060808401511660808501528060a08401511660a0850152505063ffffffff60c08201511660c083015260e081015161092660e084018263ffffffff169052565b6101008101610dfb8284614fab565b5f806040838503121561504a575f80fd5b82359150602083013561505c81614c55565b809150509250929050565b80516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b83815261018081016150af6020830185615067565b61294460a0830184614bc6565b60808101610dfb8284615067565b61016081016150d98285615067565b610b8b6080830184614bc6565b5f805f80604085870312156150f9575f80fd5b84356001600160401b038082111561510f575f80fd5b61511b88838901614b39565b90965094506020870135915080821115615133575f80fd5b5061514087828801614b39565b95989497509550505050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015161519260a08401826001600160a01b03169052565b5060c08101516151ad60c08401826001600160401b03169052565b5060e08101516151c560e084018263ffffffff169052565b50610100818101516001600160401b039081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015115159083015261018080820151908301526101a0808201516001600160a01b03811682850152612356565b5f815180845260208085019450602084015f5b8381101561528e57815180516001600160a01b03168852838101516001600160601b0316848901526040908101516001600160401b03169088015260609096019590820190600101615241565b509495945050505050565b5f6101e06152a7838661514c565b806101c08401526152ba8184018561522e565b95945050505050565b5f80604083850312156152d4575f80fd5b82356152df81614b15565b946020939093013593505050565b5f602082840312156152fd575f80fd5b8135610b8b81614c55565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b61ffff81168114610b79575f80fd5b8035614b3481615356565b5f60808284031215615380575f80fd5b604051608081018181106001600160401b03821117156153a2576153a2614d17565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b5f604082840312156153e3575f80fd5b6153eb614d2b565b905081356153f881615356565b815260208201356001600160401b03811115615412575f80fd5b61541e84828501614dc8565b60208301525092915050565b5f805f83850361026081121561543e575f80fd5b6101c08082121561544d575f80fd5b615455614d53565b9150853582526020860135602083015260408601356040830152606086013560608301526080860135608083015261548f60a08701614c4a565b60a08301526154a060c08701614b29565b60c08301526154b160e08701614e7f565b60e08301526101006154c4818801614b29565b908301526101206154d6878201614b29565b908301526101406154e8878201615365565b908301526101606154fa878201614c62565b9083015261018086810135908301526101a0615517818801614c4a565b818401525081945061552b87828801615370565b935050506102408401356001600160401b03811115615548575f80fd5b615554868287016153d3565b9150509250925092565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b038084168061562f57634e487b7160e01b5f52601260045260245ffd5b92169190910692915050565b6101c08101610dfb828461514c565b5f6020828403121561565a575f80fd5b8151610b8b81614c36565b80516001600160601b0381168114614b34575f80fd5b5f60c0828403121561568b575f80fd5b615693614d76565b825181526156a360208401615665565b60208201526156b460408401615665565b6040820152606083015162ffffff811681146156ce575f80fd5b606082015260808301516156e181615356565b608082015260a083015160ff811681146156f9575f80fd5b60a08201529392505050565b5f5b8381101561571f578181015183820152602001615707565b50505f910152565b5f815180845261573e816020860160208601615705565b601f01601f19169290920160200192915050565b61ffff81511682525f6020820151604060208501526129446040850182615727565b83518152602080850151818301526040808601516001600160a01b03908116828501526060808801516001600160401b03168186015260808089015115159086015260a08089015115159086015260c08089015190921691850191909152855160e0850152918501516101008401528401516101208301528301516101408201525f6101808061016084015261470981840185615752565b8051602080830151919081101561582c575f198160200360031b1b821691505b50919050565b845181526020808601519082015260408086015190820152606094850151948101949094526001600160a01b039290921660808401526001600160601b031660a083015261ffff1660c082015260e00190565b634e487b7160e01b5f52600160045260245ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f602082840312156158f4575f80fd5b5051919050565b5f82601f83011261590a575f80fd5b813560206001600160401b038083111561592657615926614d17565b8260051b615935838201614d98565b938452858101830193838101908886111561594e575f80fd5b84880192505b858310156159cb5782358481111561596a575f80fd5b88016040818b03601f1901811315615980575f80fd5b615988614d2b565b8783013561599581614c36565b81529082013590868211156159a8575f80fd5b6159b68c8984860101614dc8565b81890152845250509184019190840190615954565b98975050505050505050565b5f602082840312156159e7575f80fd5b81356001600160401b03808211156159fd575f80fd5b9083019060c08286031215615a10575f80fd5b615a18614d76565b615a2183614c4a565b8152615a2f60208401614c4a565b60208201526040830135604082015260608301356060820152608083013582811115615a59575f80fd5b615a65878286016158fb565b60808301525060a083013582811115615a7c575f80fd5b615a8887828601614dc8565b60a08301525095945050505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115615acb57615acb615a97565b5092915050565b6001600160401b03828116828216039080821115615acb57615acb615a97565b818382375f9101908152919050565b5f60208284031215615b11575f80fd5b8151610b8b81615356565b634e487b7160e01b5f52603260045260245ffd5b5f6102e0615b3e8387614fab565b615b4c61010084018661514c565b806102c084015261470981840185615727565b80820180821115610dfb57610dfb615a97565b5f6102006001600160601b0386168352615b8f602084018661514c565b806101e08401526147098184018561522e565b8082028115828204841417610dfb57610dfb615a97565b5f8060408385031215615bca575f80fd5b8251615bd581614b15565b6020939093015192949293505050565b5f60208284031215615bf5575f80fd5b8151610b8b81614c55565b634e487b7160e01b5f52602160045260245ffd5b5f8251615c25818460208701615705565b9190910192915050565b602081525f610b8b602083018461572756fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b3e425cc7b159736510691b63a25b13106646b075557c8ac4e8c9362e658cfc464736f6c63430008180033
Deployed Bytecode
0x6080604052600436106101bd575f3560e01c806379ba5097116100f2578063c782156811610092578063ef16e84511610062578063ef16e845146106b8578063f2fde38b146106d9578063fd257e29146106f8578063ff00c39114610717575f80fd5b8063c7821568146105b2578063dde89cf51461063c578063e07baba61461065e578063e30c39781461069b575f80fd5b80638da5cb5b116100cd5780638da5cb5b1461040a578063a86f9d9e14610427578063c19d93fb14610446578063c3f909d414610526575f80fd5b806379ba5097146103c35780638456cb59146103d75780638778209d146103eb575f80fd5b80633f4ba83a1161015d578063563479a511610138578063563479a5146103275780635c975abb146103535780635fa15e7914610383578063715018a6146103af575f80fd5b80633f4ba83a146102de5780634f1ef286146102f257806352d1902d14610305575f80fd5b806329d1b62f1161019857806329d1b62f1461024a5780633659cfe6146102695780633ab76e9f146102885780633eb6b8cf146102bf575f80fd5b8063069489a2146101ed57806310d008bd1461020157806319e8dce214610220575f80fd5b366101e9576101ca610736565b6101e757604051630d28633960e01b815260040160405180910390fd5b005b5f80fd5b3480156101f8575f80fd5b506101e761074a565b34801561020c575f80fd5b506101e761021b366004614b76565b610802565b34801561022b575f80fd5b5061023461092b565b6040516102419190614c28565b60405180910390f35b348015610255575f80fd5b506101e7610264366004614c6d565b6109b4565b348015610274575f80fd5b506101e7610283366004614cbd565b610a9f565b348015610293575f80fd5b506097546102a7906001600160a01b031681565b6040516001600160a01b039091168152602001610241565b3480156102ca575f80fd5b506102a76102d9366004614cd8565b610b7c565b3480156102e9575f80fd5b506101e7610b92565b6101e7610300366004614e33565b610bbd565b348015610310575f80fd5b50610319610c8c565b604051908152602001610241565b348015610332575f80fd5b50610346610341366004614e92565b610d3d565b6040516102419190614ec5565b34801561035e575f80fd5b5061037360c954610100900460ff1660021490565b6040519015158152602001610241565b34801561038e575f80fd5b506103a261039d366004614f90565b610e01565b604051610241919061502a565b3480156103ba575f80fd5b506101e7610ee8565b3480156103ce575f80fd5b506101e7610efb565b3480156103e2575f80fd5b506101e7610f72565b3480156103f6575f80fd5b506101e7610405366004614f90565b610f85565b348015610415575f80fd5b506033546001600160a01b03166102a7565b348015610432575f80fd5b506102a7610441366004615039565b611040565b348015610451575f80fd5b5060fe54604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c0830152610517929183565b6040516102419392919061509a565b348015610531575f80fd5b5061053a61104c565b60405161024191905f60e0820190506001600160401b038084511683528060208501511660208401528060408501511660408401528060608501511660608401525063ffffffff60808401511660808301526001600160601b0360a08401511660a083015260ff60c08401511660c083015292915050565b3480156105bd575f80fd5b5061062f604080516080810182525f808252602082018190529181018290526060810191909152506040805160808101825260ff546001600160401b038082168352600160401b820481166020840152600160801b8204811693830193909352600160c01b9004909116606082015290565b60405161024191906150bc565b348015610647575f80fd5b506106506110d3565b6040516102419291906150ca565b348015610669575f80fd5b5060c954610683906201000090046001600160401b031681565b6040516001600160401b039091168152602001610241565b3480156106a6575f80fd5b506065546001600160a01b03166102a7565b6106cb6106c63660046150e6565b6111bd565b604051610241929190615299565b3480156106e4575f80fd5b506101e76106f3366004614cbd565b611291565b348015610703575f80fd5b506103466107123660046152c3565b611302565b348015610722575f80fd5b506101e76107313660046152ed565b61131e565b5f6002610741611333565b60ff1614905090565b610752611372565b5f54600290610100900460ff1615801561077257505f5460ff8083169116105b6107975760405162461bcd60e51b815260040161078e90615308565b60405180910390fd5b5f8054610100805466ffffffffffffff60881b1916815560fe83905561ff001960ff851661ffff199093168317909117169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a150565b61081660c954610100900460ff1660021490565b156108345760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610860576040516333018e5560e11b815260040160405180910390fd5b600261086a611333565b60ff160361088b5760405163dfc60d8560e01b815260040160405180910390fd5b61089560026113cc565b5f80806108a48486018661542a565b9250925092508260c001516001600160401b0316866001600160401b0316146108e057604051638a1c400f60e01b815260040160405180910390fd5b5f6108e961104c565b90505f6108fb60fb8330888888611414565b905061090d60fb83308460ff16611de6565b505050505061091c60fb61235c565b61092660016113cc565b505050565b61093361497e565b506040805160e081018252610100546001600160401b038082168352600160401b82048116602084015260ff600160801b83048116151594840194909452600160881b8204909316606083015261ffff600160901b820416608083015263ffffffff600160a01b82041660a0830152600160c01b900490911660c082015290565b5f54610100900460ff16158080156109d257505f54600160ff909116105b806109eb5750303b1580156109eb57505f5460ff166001145b610a075760405162461bcd60e51b815260040161078e90615308565b5f805460ff191660011790558015610a28575f805461ff0019166101001790555b610a3285856123f1565b610a4560fb610a3f61104c565b85612450565b8115610a5357610a536125c8565b8015610a98575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b037f00000000000000000000000099ba70e62cab0cb983e66f72330fbddc11d85501163003610ae75760405162461bcd60e51b815260040161078e9061555e565b7f00000000000000000000000099ba70e62cab0cb983e66f72330fbddc11d855016001600160a01b0316610b2f5f80516020615c42833981519152546001600160a01b031690565b6001600160a01b031614610b555760405162461bcd60e51b815260040161078e906155aa565b610b5e8161263f565b604080515f80825260208201909252610b7991839190612647565b50565b5f610b888484846127b1565b90505b9392505050565b610b9a6128a2565b61010080546001600160c01b0316600160c01b426001600160401b031602179055565b6001600160a01b037f00000000000000000000000099ba70e62cab0cb983e66f72330fbddc11d85501163003610c055760405162461bcd60e51b815260040161078e9061555e565b7f00000000000000000000000099ba70e62cab0cb983e66f72330fbddc11d855016001600160a01b0316610c4d5f80516020615c42833981519152546001600160a01b031690565b6001600160a01b031614610c735760405162461bcd60e51b815260040161078e906155aa565b610c7c8261263f565b610c8882826001612647565b5050565b5f306001600160a01b037f00000000000000000000000099ba70e62cab0cb983e66f72330fbddc11d855011614610d2b5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c0000000000000000606482015260840161078e565b505f80516020615c4283398151915290565b610d456149b9565b610d5960fb610d5261104c565b85856128b4565b6040805161014081018252825481526001830154602082015260028301549181019190915260038201546001600160a01b0380821660608401526001600160601b03600160a01b9283900481166080850152600485015491821660a08501529190041660c08201526005909101546001600160401b03811660e083015261ffff600160401b82041661010083015260ff600160501b9091041661012082015290505b92915050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152610e5460fb610e4e61104c565b8461294c565b5060408051610100810182528254815260018301546001600160a01b03811660208301526001600160601b03600160a01b90910416918101919091526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b82041660a083015263ffffffff600160c01b8204811660c0840152600160e01b9091041660e082015292915050565b610ef0611372565b610ef95f6129ac565b565b60655433906001600160a01b03168114610f695760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161078e565b610b79816129ac565b610f7a6125c8565b610ef93360016129c5565b610f9960c954610100900460ff1660021490565b15610fb75760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610fe3576040516333018e5560e11b815260040160405180910390fd5b6002610fed611333565b60ff160361100e5760405163dfc60d8560e01b815260040160405180910390fd5b61101860026113cc565b61102c60fb61102561104c565b3084611de6565b61103660fb61235c565b610b7960016113cc565b5f610b8b4684846127b1565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810191909152506040805160e08101825262028c588152622dc6c06020820152622dedd091810191909152600a6060820152630e4e1c006080820152680d8d726b7177a8000060a0820152601060c082015290565b604080516080810182525f8082526020820181905291810182905260608101919091526110fe61497e565b5050604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015291565b6111c5614a0c565b60606111db60c954610100900460ff1660021490565b156111f95760405163bae6e2a960e01b815260040160405180910390fd5b6002611203611333565b60ff16036112245760405163dfc60d8560e01b815260040160405180910390fd5b61122e60026113cc565b5f61123761104c565b905061124b60fb82308a8a8a8a6001612a44565b610100549194509250600160801b900460ff166112735761127360fb82308460600151611de6565b5061127e60fb61235c565b61128860016113cc565b94509492505050565b611299611372565b606580546001600160a01b0383166001600160a01b031990911681179091556112ca6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61130a6149b9565b610d5960fb61131761104c565b85856134fb565b61132833826129c5565b610b7960fb82613582565b5f61133d4661362f565b1561136857507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b6033546001600160a01b03163314610ef95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161078e565b6113d54661362f565b1561140057807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b81515f90158061142657506020830151155b8061143357506040830151155b15611451576040516317eddea160e11b815260040160405180910390fd5b611459614a7f565b6040805160e08101825260058a01546001600160401b038082168352600160401b820481166020840190815260ff600160801b84048116151595850195909552600160881b8304909416606084015261ffff600160901b830416608084015263ffffffff600160a01b83041660a0840152600160c01b909104811660c080840191909152918452915190870151908216911611158061150b575080515160c08601516001600160401b03918216911610155b1561152957604051638a1c400f60e01b815260040160405180910390fd5b86604001518560c0015161153d919061560a565b6001600160401b0390811660a083018190525f90815260208a90526040908190206002810154831660c080860182905260018301546001600160a01b03166060870152825493860193909352918801519092161415806115c75750856040516020016115a9919061563b565b60405160208183030381529060405280519060200120826040015114155b156115e557604051632ec3485560e11b815260040160405180910390fd5b5f6115f28a83888661365c565b63ffffffff90911660e0850152855190915061ffff161580611623575086610140015161ffff16855f015161ffff16105b8061164157506005810154855161ffff600160401b90920482169116105b1561165f57604051631a32f51360e01b815260040160405180910390fd5b604051635437cecf60e11b81526c3a34b2b92fb83937bb34b232b960991b60048201525f60248201526001600160a01b0389169063a86f9d9e90604401602060405180830381865afa1580156116b7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116db919061564a565b855160405163576c3de760e01b815261ffff90911660048201526001600160a01b03919091169063576c3de79060240160c060405180830381865afa158015611726573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061174a919061567b565b602084018190526005820154845160c0015160809092015161177d926001600160401b0392831692169061ffff166137e9565b156101408401526020830151604001516001600160601b0316158015906117af575060048101546001600160a01b0316155b80156117c557508260e0015163ffffffff166001145b80156117de57506005810154600160401b900461ffff16155b80156117ec57508261014001515b156118275782606001516001600160a01b0316336001600160a01b03161461182757604051632185a2ad60e21b815260040160405180910390fd5b6020830151511561199157602083015151604051635437cecf60e11b815260048101919091525f60248201819052906001600160a01b038a169063a86f9d9e90604401602060405180830381865afa158015611885573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118a9919061564a565b600583015487519192505f9161ffff908116600160401b909204161480156118e157506020850151604001516001600160601b031615155b6040805160e0810182528782015181528b82015160208201523381830181905260c0808a01516001600160401b0316606084015284151560808401526101608e0151151560a0840152820152905163043d132d60e31b8152919250906001600160a01b038416906321e89968906119609084908d908d90600401615774565b5f604051808303815f87803b158015611977575f80fd5b505af1158015611989573d5f803e3d5ffd5b505050505050505b60208301516040908101516001600160601b03161561012085015251635437cecf60e11b81526a3a30b4b5b7afba37b5b2b760a91b60048201525f60248201819052906001600160a01b038a169063a86f9d9e90604401602060405180830381865afa158015611a03573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a27919061564a565b6001840154600160a01b90046001600160601b0316608086015261012085015190915015611af35760808401516001600160601b031615611af35783610140015180611aaf57508560200151516020148015611aaf57507f20d34d7a20a139f9be221ba2163925c0c86ed02d34033f288f010d23a63ef4b78660200151611aad9061580c565b145b15611adb5760608401516080850151611adb916001600160a01b038416916001600160601b0316613806565b6001830180546001600160a01b031690555f60808501525b81600101548760200151148015611b11575081600201548760400151145b15156101608501526005820154865161ffff600160401b909204821691161115611b9e57611b43838389898886613869565b8360c001516001600160401b03167fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f88338760200151602001518a5f0151604051611b919493929190615832565b60405180910390a2611db4565b83610160015115611bc257604051639d49773160e01b815260040160405180910390fd5b83610120015115611c955760208085015101516001600160601b031615611beb57611beb615885565b6003820154600160a01b90046001600160601b0316158015611c18575060048201546001600160a01b0316155b611c2457611c24615885565b6003820180546001600160a01b0319163390811790915560208801516001840155604080890151600285015560c0860151885191516001600160401b03909116927fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f92611b91928c92915f91615832565b60048201546001600160a01b031615611cc1576040516382ef169960e01b815260040160405180910390fd5b6005820154845160c00151602086015160600151611cf1926001600160401b0390811692169062ffffff166137e9565b15611d0f5760405163378b1eff60e21b815260040160405180910390fd5b602084015160400151611d39906001600160a01b03831690339030906001600160601b0316613b07565b6020840151604090810151336001600160a01b0319600160a01b6001600160601b03841602168117600486015560c0870151895193516001600160401b03909116937fb4c0a86c1ff239277697775b1e91d3375fd3a5ef6b345aa4e2f6001c890558f693611dab938d93909290615832565b60405180910390a25b50600501805467ffffffffffffffff1916426001600160401b0316179055506020015160a00151979650505050505050565b6001600160401b03811615612356576040805160e08101825260058601546001600160401b038082168352600160401b820481166020840181905260ff600160801b84048116151585870152600160881b840416606085015261ffff600160901b840416608085015263ffffffff600160a01b84041660a0850152600160c01b9092041660c0830152918501519091905f90611e82908361560a565b6001600160401b038082165f90815260208a905260409020600281015492935091811690841614611ec657604051632ec3485560e11b815260040160405180910390fd5b6002810154600160e01b900463ffffffff165f819003611ef95760405163d4345b9760e01b815260040160405180910390fd5b6001600160401b0383165f90815260028a016020908152604080832063ffffffff85168452909152808220600101549051635437cecf60e11b81526a3a30b4b5b7afba37b5b2b760a91b6004820152602481018390529091908190819081906001600160a01b038d169063a86f9d9e90604401602060405180830381865afa158015611f87573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fab919061564a565b90508860010198505b895f01516001600160401b0316896001600160401b0316108015611fe957508a6001600160401b0316836001600160401b0316105b156122f6578c604001516001600160401b0316896001600160401b031681612013576120136155f6565b0697508d5f015f896001600160401b03166001600160401b031681526020019081526020015f209650886001600160401b0316876002015f9054906101000a90046001600160401b03166001600160401b03161461208457604051632ec3485560e11b815260040160405180910390fd5b6120908e888a88613b3f565b955063ffffffff8616156122f6576001600160401b0388165f90815260028f016020908152604080832063ffffffff8a168452909152902060048101546001600160a01b0316156120e157506122f6565b6001600160a01b03831661216e57604051635437cecf60e11b81526c3a34b2b92fb83937bb34b232b960991b60048201525f60248201526001600160a01b038e169063a86f9d9e90604401602060405180830381865afa158015612147573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216b919061564a565b92505b600581015460c08c015160405163576c3de760e01b8152600160401b830461ffff166004820152612208926001600160401b039081169216906001600160a01b0387169063576c3de79060240160c060405180830381865afa1580156121d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121fa919061567b565b6060015162ffffff166137e9565b61221257506122f6565b6002808901805463ffffffff808b16600160e01b026001600160e01b039092169190911790915560018301549183015460038401549298509650612278916001600160a01b0385811692908216916001600160601b03600160a01b909104169061380616565b600381015460058201546040805189815260208101899052600160401b90920461ffff16908201526001600160a01b03909116906001600160401b038c16907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a389600101995083600101935050611fb4565b6001600160401b0383161561234b5760208a015160058f0180546001600160401b03928601928316600160401b026fffffffffffffffff0000000000000000199091161790556123498f8f8f8489613bda565b505b505050505050505050505b50505050565b7fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b816005016040516107f791905f60e08201905082546001600160401b038082168452808260401c1660208501525060ff8160801c161515604084015260ff8160881c16606084015261ffff8160901c16608084015263ffffffff8160a01c1660a08401528060c01c60c08401525092915050565b5f54610100900460ff166124175760405162461bcd60e51b815260040161078e90615899565b6001600160a01b03811661243e576040516375cabfef60e11b815260040160405180910390fd5b61244782613e19565b610c8881613e49565b61245982613eb9565b6124765760405163223aca4d60e21b815260040160405180910390fd5b5f8190036124975760405163d6d0f75560e01b815260040160405180910390fd5b600483018054426001600160401b03908116600160401b81026fffffffffffffffffffffffffffffffff1990931643929092169190911782179092556005808601805467ffffffffffffffff1990811660019081179092555f80805260208981526040808320600280820180546001600160e01b037fffffffff00000000ffffffffffffffff0000000000000000ffffffffffffffff909116909a17600160c11b1799909916600160e01b17909855858155968b01825280832085845282528083209485018990556003850180546001600160a01b031916905594840180549093169096179091558251868152948501819052918401829052919281907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a35050505050565b6125dc60c954610100900460ff1660021490565b156125fa5760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b610b79611372565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561267a5761092683613f65565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156126d4575060408051601f3d908101601f191682019092526126d1918101906158e4565b60015b6127375760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b606482015260840161078e565b5f80516020615c4283398151915281146127a55760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b606482015260840161078e565b50610926838383614000565b6097545f906001600160a01b0316806127dd57604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0386166004820152602481018590526001600160a01b038216906328f713cc90604401602060405180830381865afa15801561282f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612853919061564a565b91508215801561286a57506001600160a01b038216155b1561289a57604051632b0d65db60e01b81526001600160401b03861660048201526024810185905260440161078e565b509392505050565b6128aa614024565b610ef9335f6129c5565b5f6128bf85846140ae565b5f806128cc87878761294c565b915091508363ffffffff165f14806128f95750600282015463ffffffff600160c01b909104811690851610155b156129175760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b03165f908152600287016020908152604080832063ffffffff8716845290915290209150505b949350505050565b5f8083604001518361295e919061560a565b6001600160401b038181165f90815260208890526040902060028101549094509192508481169116146129a457604051638a1c400f60e01b815260040160405180910390fd5b935093915050565b606580546001600160a01b0319169055610b7981614172565b6d636861696e5f7761746368646f6760901b6129e96033546001600160a01b031690565b6001600160a01b0316336001600160a01b031614158015612a265750612a10816001611040565b6001600160a01b0316336001600160a01b031614155b1561092657604051630d85cccf60e11b815260040160405180910390fd5b612a4c614a0c565b60605f612a5b878901896159d7565b80519091506001600160a01b0316612a865760405163041bee0760e41b815260040160405180910390fd5b60208101516001600160a01b0316612a9f573360208201525b6040805160e08101825260058d01546001600160401b038082168352600160401b82048116602084015260ff600160801b83048116151594840194909452600160881b8204909316606083015261ffff600160901b820416608083015263ffffffff600160a01b82041660a0830152600160c01b900490911660c0820152612b27818b6141c3565b612b4457604051631231017d60e01b815260040160405180910390fd5b8a602001518160200151612b589190615aab565b612b63906001615aab565b6001600160401b0316815f01516001600160401b031610612b97576040516351ec7d5360e01b815260040160405180910390fd5b5f8c5f015f8d604001516001855f0151612bb19190615ad2565b612bbb919061560a565b6001600160401b0316815260208101919091526040015f2054606084015190915015801590612bee575082606001518114155b15612c0c57604051630d41ec8760e11b815260040160405180910390fd5b604051806101c00160405280600143034081526020015f801b81526020015f801b8152602001846040015181526020017f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd5f1b815260200184602001516001600160a01b03168152602001835f01516001600160401b031681526020018d6080015163ffffffff168152602001426001600160401b03168152602001600143036001600160401b031681526020015f61ffff168152602001898990505f1415158152602001828152602001336001600160a01b0316815250945084610160015115612d4557612cfa4661362f565b612d175760405163df9969ef60e01b815260040160405180910390fd5b5f8049604087018190529003612d4057604051639e7e2ddd60e01b815260040160405180910390fd5b612dcc565b8787604051612d55929190615af2565b604080519182900390912090860152858015612d7f57508460c001516001600160401b0316600114155b8015612dae5750336001600160a01b0316612da286604001518560a00151614319565b6001600160a01b031614155b15612dcc5760405163f6ee3bdb60e01b815260040160405180910390fd5b81516040805144602082015260c09290921b6001600160c01b0319169082015243604882015260680160408051808303601f1901815291815281516020928301209187019190915251635437cecf60e11b81526c3a34b2b92fb83937bb34b232b960991b60048201525f60248201526001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015612e6a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e8e919061564a565b60208601516040516359ab4e2360e01b81526001600160a01b0392909216916359ab4e2391612ec39160040190815260200190565b602060405180830381865afa158015612ede573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f029190615b01565b61ffff166101408601526040805161010081019091525f9080612f2988610120830161563b565b604051602081830303815290604052805190602001208152602001855f01516001600160a01b031681526020018e60a001516001600160601b03168152602001845f01516001600160401b031681526020018761010001516001600160401b03168152602001436001600160401b03168152602001600163ffffffff1681526020015f63ffffffff168152509050808e5f015f8f60400151865f0151612fcf919061560a565b6001600160401b03166001600160401b031681526020019081526020015f205f820151815f01556020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160601b0302191690836001600160601b031602179055506060820151816002015f6101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160020160086101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160020160106101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160020160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600201601c6101000a81548163ffffffff021916908363ffffffff1602179055509050508d6005015f015f81819054906101000a90046001600160401b031660010191906101000a8154816001600160401b0302191690836001600160401b031602179055505f8c6001600160a01b031663a86f9d9e6a3a30b4b5b7afba37b5b2b760a91b5f6040518363ffffffff1660e01b81526004016131b09291909182521515602082015260400190565b602060405180830381865afa1580156131cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ef919061564a565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa158015613236573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061325a91906158e4565b90505f805b87608001515181101561338a578760800151818151811061328257613282615b1c565b60200260200101515f01516001600160a01b0316826001600160a01b0316106132be5760405163390ed16960e21b815260040160405180910390fd5b876080015181815181106132d4576132d4615b1c565b60200260200101515f01516001600160a01b03166336b6ea4e47878d8c60800151868151811061330657613306615b1c565b6020026020010151602001516040518563ffffffff1660e01b815260040161333093929190615b30565b5f604051808303818588803b158015613347575f80fd5b505af1158015613359573d5f803e3d5ffd5b50505050508760800151818151811061337457613374615b1c565b602090810291909101015151915060010161325f565b50471561339b5761339b3347614333565b8f60a001516001600160601b0316826133b49190615b5f565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa1580156133f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061341a91906158e4565b1461343857604051631bf37e2160e11b815260040160405180910390fd5b505f91506134439050565b60405190808252806020026020018201604052801561348c57816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816134615790505b50945080602001516001600160a01b031681606001516001600160401b03167fcda4e564245eb15494bc6da29f6a42e1941cf57f5314bf35bab8a1fca0a9c60a8f60a0015189896040516134e293929190615b72565b60405180910390a3505050509850989650505050505050565b5f61350685846140ae565b5f8061351387878761294c565b915091505f61352488848488613b3f565b90508063ffffffff165f0361354c5760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b039091165f908152600288016020908152604080832063ffffffff909416835292905220915050949350505050565b6005820154811515600160801b90910460ff161515036135b55760405163689d009d60e11b815260040160405180910390fd5b60058201805460ff60801b1916600160801b83151502179055806135f6576005820180546001600160c01b0316600160c01b426001600160401b0316021790555b60405181151581527fed64db85835d07c3c990b8ebdd55e32d64e5ed53143b6ef2179e7bfaf17ddc3b9060200160405180910390a15050565b5f6001821480613640575061426882145b8061364d575062aa36a782145b80610dfb5750610dfb8261433e565b5f8061367186868560a00151875f0151613b3f565b91508163ffffffff165f036137b157505060028084018054600163ffffffff600160c01b80840482168381019092160263ffffffff60c01b1990931692909217835560a08501516001600160401b039081165f908152898601602090815260408083208684529091528120808401829055958601556003850180546001600160a01b03169055600160a01b600486015592546005850180546affffffffffffffffffffff1916600160401b90920490941617909255919082900361375e578351815560608301516003820180546001600160a01b0319166001600160a01b03909216919091179055611288565b6003810180546001600160a01b031916905560c08301516001600160401b03165f9081526001870160209081526040808320875184529091529020805463ffffffff191663ffffffff8416179055611288565b5060a08201516001600160401b03165f908152600286016020908152604080832063ffffffff85168452909152902094509492505050565b5f80603c83026137f98686614355565b0142101595945050505050565b6040516001600160a01b03831660248201526044810182905261092690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261436a565b60048501545f906001600160a01b03161561394f57826101600151156138dd5760048601546138a790600160a01b90046001600160601b031661443d565b60038701549091506138d8906001600160a01b038481169190811690600160a01b90046001600160601b0316613806565b6139f2565b60038601546002906138fe90600160a01b90046001600160601b031661443d565b6004880154911c91506138d8906001600160a01b031661391f836003615ba2565b600489015461393e9190600160a01b90046001600160601b0316615b5f565b6001600160a01b0385169190613806565b8261016001511561397357604051639d49773160e01b815260040160405180910390fd5b600386015461399190600160a01b90046001600160601b031661443d565b905082608001516001600160601b03165f146139f25760608301516001600160a01b0316331480156139c557508261014001515b156139da5760808301516001600160601b0316015b6001870180546001600160a01b031690555f60808401525b8260200151602001516001600160601b0316811115613a39576020808401510151613a34906001600160a01b0384169033906001600160601b03168403613806565b613a85565b8260200151602001516001600160601b0316811015613a8557613a853330838660200151602001516001600160601b031603856001600160a01b0316613b07909392919063ffffffff16565b6020808401510151600160a01b600488018190556001600160601b03909116026001600160a01b03191633176003870155835160058701805461ffff909216600160401b0269ffff000000000000000019909216919091179055610160830151613afe5760208501516001870155604085015160028701555b50505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526123569085906323b872dd60e01b90608401613832565b6001600160401b0382165f908152600285016020908152604080832060018452909152812054829003613b7457506001613ba5565b5060028301546001600160401b03165f908152600185016020908152604080832084845290915290205463ffffffff165b600284015463ffffffff600160c01b909104811690821610612944576040516367a1907f60e01b815260040160405180910390fd5b604051635437cecf60e11b81526d7369676e616c5f7365727669636560901b60048201525f60248201819052906001600160a01b0385169063a86f9d9e90604401602060405180830381865afa158015613c36573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613c5a919061564a565b855160405163dfc8ff1d60e01b81526001600160401b0390911660048201527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da16960248201525f604482018190529192506001600160a01b0383169063dfc8ff1d906064016040805180830381865afa158015613cd8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613cfc9190615bb9565b5090508560c0015160ff1681613d129190615aab565b6001600160401b0316846001600160401b03161115613afe57600487810180546fffffffffffffffffffffffffffffffff16600160801b6001600160401b038881169182026001600160c01b031692909217600160c01b428416021790925588516040516313e4299d60e21b81529116928101929092527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da16960248301526044820152606481018490526001600160a01b03831690634f90a674906084016020604051808303815f875af1158015613deb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613e0f91906158e4565b5050505050505050565b613e376001600160a01b03821615613e3157816129ac565b336129ac565b5060c9805461ff001916610100179055565b5f54610100900460ff16613e6f5760405162461bcd60e51b815260040161078e90615899565b6001600160401b03461115613e975760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b5f6001825f01516001600160401b0316111580613edf575081516001600160401b031646145b80613ef85750600182602001516001600160401b031611155b80613f2857506020820151613f0e906001615aab565b6001600160401b031682604001516001600160401b031611155b80613f3b5750608082015163ffffffff16155b80613f51575060a08201516001600160601b0316155b15613f5d57505f919050565b506001919050565b6001600160a01b0381163b613fd25760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161078e565b5f80516020615c4283398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6140098361445f565b5f825111806140155750805b1561092657612356838361449e565b61403860c954610100900460ff1660021490565b6140555760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001612635565b6040805160e08101825260058401546001600160401b038082168352600160401b820481166020840181905260ff600160801b84048116151595850195909552600160881b8304909416606084015261ffff600160901b830416608084015263ffffffff600160a01b83041660a0840152600160c01b909104811660c0830152909190831610806141545750805f01516001600160401b0316826001600160401b031610155b1561092657604051638a1c400f60e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b81515f906001600160401b031660010361427a57604051635437cecf60e11b81526b70726f706f7365725f6f6e6560a01b6004820152600160248201525f906001600160a01b0384169063a86f9d9e90604401602060405180830381865afa158015614231573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614255919061564a565b90506001600160a01b03811615614278576001600160a01b031633149050610dfb565b505b604051635437cecf60e11b815267383937b837b9b2b960c11b6004820152600160248201525f906001600160a01b0384169063a86f9d9e90604401602060405180830381865afa1580156142d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906142f4919061564a565b90506001600160a01b038116158061294457506001600160a01b031633149392505050565b5f805f61432685856144c3565b9150915061289a81614505565b610c8882825a61464e565b5f617e2c8210158015610dfb575050617e90101590565b5f8183116143635781610b8b565b5090919050565b5f6143be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166146919092919063ffffffff16565b905080515f14806143de5750808060200190518101906143de9190615be5565b6109265760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161078e565b5f8115614458576003614451836007615ba2565b901c610dfb565b5f92915050565b61446881613f65565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b8b8383604051806060016040528060278152602001615c626027913961469f565b5f8082516041036144f7576020830151604084015160608501515f1a6144eb87828585614713565b945094505050506144fe565b505f905060025b9250929050565b5f81600481111561451857614518615c00565b036145205750565b600181600481111561453457614534615c00565b036145815760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161078e565b600281600481111561459557614595615c00565b036145e25760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161078e565b60038160048111156145f6576145f6615c00565b03610b795760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161078e565b815f0361465a57505050565b61467483838360405180602001604052805f8152506147cd565b61092657604051634c67134d60e11b815260040160405180910390fd5b6060610b8884845f8561480a565b60605f80856001600160a01b0316856040516146bb9190615c14565b5f60405180830381855af49150503d805f81146146f3576040519150601f19603f3d011682016040523d82523d5f602084013e6146f8565b606091505b5091509150614709868383876148e1565b9695505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561474857505f90506003611288565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015614799573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b0381166147c1575f60019250925050611288565b965f9650945050505050565b5f6001600160a01b0385166147f557604051634c67134d60e11b815260040160405180910390fd5b5f80835160208501878988f195945050505050565b60608247101561486b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161078e565b5f80866001600160a01b031685876040516148869190615c14565b5f6040518083038185875af1925050503d805f81146148c0576040519150601f19603f3d011682016040523d82523d5f602084013e6148c5565b606091505b50915091506148d6878383876148e1565b979650505050505050565b6060831561494f5782515f03614948576001600160a01b0385163b6149485760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161078e565b5081612944565b61294483838151156149645781518083602001fd5b8060405162461bcd60e51b815260040161078e9190615c2f565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b604080516101c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b604051806101800160405280614a9361497e565b81526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101409091015290565b6001600160401b0381168114610b79575f80fd5b8035614b3481614b15565b919050565b5f8083601f840112614b49575f80fd5b5081356001600160401b03811115614b5f575f80fd5b6020830191508360208285010111156144fe575f80fd5b5f805f60408486031215614b88575f80fd5b8335614b9381614b15565b925060208401356001600160401b03811115614bad575f80fd5b614bb986828701614b39565b9497909650939450505050565b6001600160401b0380825116835280602083015116602084015260408201511515604084015260ff606083015116606084015261ffff608083015116608084015263ffffffff60a08301511660a08401528060c08301511660c0840152505050565b60e08101610dfb8284614bc6565b6001600160a01b0381168114610b79575f80fd5b8035614b3481614c36565b8015158114610b79575f80fd5b8035614b3481614c55565b5f805f8060808587031215614c80575f80fd5b8435614c8b81614c36565b93506020850135614c9b81614c36565b9250604085013591506060850135614cb281614c55565b939692955090935050565b5f60208284031215614ccd575f80fd5b8135610b8b81614c36565b5f805f60608486031215614cea575f80fd5b8335614cf581614b15565b9250602084013591506040840135614d0c81614c55565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715614d4d57614d4d614d17565b60405290565b6040516101c081016001600160401b0381118282101715614d4d57614d4d614d17565b60405160c081016001600160401b0381118282101715614d4d57614d4d614d17565b604051601f8201601f191681016001600160401b0381118282101715614dc057614dc0614d17565b604052919050565b5f82601f830112614dd7575f80fd5b81356001600160401b03811115614df057614df0614d17565b614e03601f8201601f1916602001614d98565b818152846020838601011115614e17575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614e44575f80fd5b8235614e4f81614c36565b915060208301356001600160401b03811115614e69575f80fd5b614e7585828601614dc8565b9150509250929050565b803563ffffffff81168114614b34575f80fd5b5f8060408385031215614ea3575f80fd5b8235614eae81614b15565b9150614ebc60208401614e7f565b90509250929050565b5f610140820190508251825260208301516020830152604083015160408301526060830151614eff60608401826001600160a01b03169052565b506080830151614f1a60808401826001600160601b03169052565b5060a0830151614f3560a08401826001600160a01b03169052565b5060c0830151614f5060c08401826001600160601b03169052565b5060e0830151614f6b60e08401826001600160401b03169052565b506101008381015161ffff16908301526101209283015160ff16929091019190915290565b5f60208284031215614fa0575f80fd5b8135610b8b81614b15565b8051825260018060a01b0360208201511660208301526001600160601b03604082015116604083015260608101516001600160401b0380821660608501528060808401511660808501528060a08401511660a0850152505063ffffffff60c08201511660c083015260e081015161092660e084018263ffffffff169052565b6101008101610dfb8284614fab565b5f806040838503121561504a575f80fd5b82359150602083013561505c81614c55565b809150509250929050565b80516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b83815261018081016150af6020830185615067565b61294460a0830184614bc6565b60808101610dfb8284615067565b61016081016150d98285615067565b610b8b6080830184614bc6565b5f805f80604085870312156150f9575f80fd5b84356001600160401b038082111561510f575f80fd5b61511b88838901614b39565b90965094506020870135915080821115615133575f80fd5b5061514087828801614b39565b95989497509550505050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015161519260a08401826001600160a01b03169052565b5060c08101516151ad60c08401826001600160401b03169052565b5060e08101516151c560e084018263ffffffff169052565b50610100818101516001600160401b039081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015115159083015261018080820151908301526101a0808201516001600160a01b03811682850152612356565b5f815180845260208085019450602084015f5b8381101561528e57815180516001600160a01b03168852838101516001600160601b0316848901526040908101516001600160401b03169088015260609096019590820190600101615241565b509495945050505050565b5f6101e06152a7838661514c565b806101c08401526152ba8184018561522e565b95945050505050565b5f80604083850312156152d4575f80fd5b82356152df81614b15565b946020939093013593505050565b5f602082840312156152fd575f80fd5b8135610b8b81614c55565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b61ffff81168114610b79575f80fd5b8035614b3481615356565b5f60808284031215615380575f80fd5b604051608081018181106001600160401b03821117156153a2576153a2614d17565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b5f604082840312156153e3575f80fd5b6153eb614d2b565b905081356153f881615356565b815260208201356001600160401b03811115615412575f80fd5b61541e84828501614dc8565b60208301525092915050565b5f805f83850361026081121561543e575f80fd5b6101c08082121561544d575f80fd5b615455614d53565b9150853582526020860135602083015260408601356040830152606086013560608301526080860135608083015261548f60a08701614c4a565b60a08301526154a060c08701614b29565b60c08301526154b160e08701614e7f565b60e08301526101006154c4818801614b29565b908301526101206154d6878201614b29565b908301526101406154e8878201615365565b908301526101606154fa878201614c62565b9083015261018086810135908301526101a0615517818801614c4a565b818401525081945061552b87828801615370565b935050506102408401356001600160401b03811115615548575f80fd5b615554868287016153d3565b9150509250925092565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b038084168061562f57634e487b7160e01b5f52601260045260245ffd5b92169190910692915050565b6101c08101610dfb828461514c565b5f6020828403121561565a575f80fd5b8151610b8b81614c36565b80516001600160601b0381168114614b34575f80fd5b5f60c0828403121561568b575f80fd5b615693614d76565b825181526156a360208401615665565b60208201526156b460408401615665565b6040820152606083015162ffffff811681146156ce575f80fd5b606082015260808301516156e181615356565b608082015260a083015160ff811681146156f9575f80fd5b60a08201529392505050565b5f5b8381101561571f578181015183820152602001615707565b50505f910152565b5f815180845261573e816020860160208601615705565b601f01601f19169290920160200192915050565b61ffff81511682525f6020820151604060208501526129446040850182615727565b83518152602080850151818301526040808601516001600160a01b03908116828501526060808801516001600160401b03168186015260808089015115159086015260a08089015115159086015260c08089015190921691850191909152855160e0850152918501516101008401528401516101208301528301516101408201525f6101808061016084015261470981840185615752565b8051602080830151919081101561582c575f198160200360031b1b821691505b50919050565b845181526020808601519082015260408086015190820152606094850151948101949094526001600160a01b039290921660808401526001600160601b031660a083015261ffff1660c082015260e00190565b634e487b7160e01b5f52600160045260245ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f602082840312156158f4575f80fd5b5051919050565b5f82601f83011261590a575f80fd5b813560206001600160401b038083111561592657615926614d17565b8260051b615935838201614d98565b938452858101830193838101908886111561594e575f80fd5b84880192505b858310156159cb5782358481111561596a575f80fd5b88016040818b03601f1901811315615980575f80fd5b615988614d2b565b8783013561599581614c36565b81529082013590868211156159a8575f80fd5b6159b68c8984860101614dc8565b81890152845250509184019190840190615954565b98975050505050505050565b5f602082840312156159e7575f80fd5b81356001600160401b03808211156159fd575f80fd5b9083019060c08286031215615a10575f80fd5b615a18614d76565b615a2183614c4a565b8152615a2f60208401614c4a565b60208201526040830135604082015260608301356060820152608083013582811115615a59575f80fd5b615a65878286016158fb565b60808301525060a083013582811115615a7c575f80fd5b615a8887828601614dc8565b60a08301525095945050505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115615acb57615acb615a97565b5092915050565b6001600160401b03828116828216039080821115615acb57615acb615a97565b818382375f9101908152919050565b5f60208284031215615b11575f80fd5b8151610b8b81615356565b634e487b7160e01b5f52603260045260245ffd5b5f6102e0615b3e8387614fab565b615b4c61010084018661514c565b806102c084015261470981840185615727565b80820180821115610dfb57610dfb615a97565b5f6102006001600160601b0386168352615b8f602084018661514c565b806101e08401526147098184018561522e565b8082028115828204841417610dfb57610dfb615a97565b5f8060408385031215615bca575f80fd5b8251615bd581614b15565b6020939093015192949293505050565b5f60208284031215615bf5575f80fd5b8151610b8b81614c55565b634e487b7160e01b5f52602160045260245ffd5b5f8251615c25818460208701615705565b9190910192915050565b602081525f610b8b602083018461572756fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b3e425cc7b159736510691b63a25b13106646b075557c8ac4e8c9362e658cfc464736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.