Feature Tip: Add private address tag to any address under My Name Tag !
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() { _; emit StateVariablesUpdated(state.slotB); } /// @dev Allows for receiving Ether from Hooks receive() external payable { if (!inNonReentrant()) revert L1_RECEIVE_DISABLED(); } /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _addressManager The address of the {AddressManager} contract. /// @param _genesisBlockHash The block hash of the genesis block. /// @param _toPause true to pause the contract by default. function init( address _owner, address _addressManager, bytes32 _genesisBlockHash, bool _toPause ) external initializer { __Essential_init(_owner, _addressManager); LibUtils.init(state, _genesisBlockHash); if (_toPause) _pause(); } function init2() external onlyOwner reinitializer(2) { // reset some previously used slots for future reuse state.slotB.__reservedB1 = 0; state.slotB.__reservedB2 = 0; state.slotB.__reservedB3 = 0; state.__reserve1 = 0; } /// @inheritdoc ITaikoL1 function proposeBlock( bytes calldata _params, bytes calldata _txList ) external payable whenNotPaused nonReentrant emitEventForClient returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_) { TaikoData.Config memory config = getConfig(); TaikoToken tko = TaikoToken(resolve(LibStrings.B_TAIKO_TOKEN, false)); (meta_, deposits_) = LibProposing.proposeBlock(state, tko, config, this, _params, _txList); if (LibUtils.shouldVerifyBlocks(config, meta_.id, true) && !state.slotB.provingPaused) { LibVerifying.verifyBlocks(state, tko, config, this, config.maxBlocksToVerify); } } /// @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(); TaikoToken tko = TaikoToken(resolve(LibStrings.B_TAIKO_TOKEN, false)); LibProving.proveBlock(state, tko, config, this, meta, tran, proof); if (LibUtils.shouldVerifyBlocks(config, meta.id, false)) { LibVerifying.verifyBlocks(state, tko, config, this, config.maxBlocksToVerify); } } /// @inheritdoc ITaikoL1 function verifyBlocks(uint64 _maxBlocksToVerify) external whenNotPaused whenProvingNotPaused nonReentrant emitEventForClient { LibVerifying.verifyBlocks( state, TaikoToken(resolve(LibStrings.B_TAIKO_TOKEN, false)), getConfig(), this, _maxBlocksToVerify ); } /// @notice Gets the details of a block. /// @param _blockId Index of the block. /// @return blk_ The block. function getBlock(uint64 _blockId) external view returns (TaikoData.Block memory blk_) { (blk_,) = LibUtils.getBlock(state, getConfig(), _blockId); } /// @notice Gets the state transition for a specific block. /// @param _blockId Index of the block. /// @param _parentHash Parent hash of the block. /// @return The state transition data of the block. function getTransition( uint64 _blockId, bytes32 _parentHash ) external view returns (TaikoData.TransitionState memory) { return LibUtils.getTransition(state, getConfig(), _blockId, _parentHash); } /// @notice Gets the state transition for a specific block. /// @param _blockId Index of the block. /// @param _tid The transition id. /// @return The state transition data of the block. function getTransition( uint64 _blockId, uint32 _tid ) external view returns (TaikoData.TransitionState memory) { return LibUtils.getTransition(state, getConfig(), _blockId, _tid); } /// @notice Returns information about the last verified block. /// @return blockId_ The last verified block's ID. /// @return blockHash_ The last verified block's blockHash. /// @return stateRoot_ The last verified block's stateRoot. function getLastVerifiedBlock() external view returns (uint64 blockId_, bytes32 blockHash_, bytes32 stateRoot_) { blockId_ = state.slotB.lastVerifiedBlockId; (blockHash_, stateRoot_) = LibUtils.getBlockInfo(state, getConfig(), blockId_); } /// @notice Returns information about the last synchronized block. /// @return blockId_ The last verified block's ID. /// @return blockHash_ The last verified block's blockHash. /// @return stateRoot_ The last verified block's stateRoot. function getLastSyncedBlock() external view returns (uint64 blockId_, bytes32 blockHash_, bytes32 stateRoot_) { blockId_ = state.slotA.lastSyncedBlockId; (blockHash_, stateRoot_) = LibUtils.getBlockInfo(state, getConfig(), blockId_); } /// @notice Gets the state variables of the TaikoL1 contract. /// @dev This method can be deleted once node/client stops using it. /// @return State variables stored at SlotA. /// @return State variables stored at SlotB. function getStateVariables() external view returns (TaikoData.SlotA memory, TaikoData.SlotB memory) { return (state.slotA, state.slotB); } /// @inheritdoc ITaikoL1 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); } /// @inheritdoc ITaikoL1 function getConfig() public pure virtual override returns (TaikoData.Config memory) { // All hard-coded configurations: // - treasury: the actual TaikoL2 address. // - anchorGasLimit: 250_000 (based on internal devnet, its ~220_000 // after 256 L2 blocks) return TaikoData.Config({ chainId: LibNetwork.TAIKO, // Assume the block time is 3s, the protocol will allow ~90 days of // new blocks without any verification. blockMaxProposals: 324_000, // = 45*86400/12, 45 days, 12 seconds avg block time blockRingBufferSize: 324_512, maxBlocksToVerify: 16, // This value is set based on `gasTargetPerL1Block = 15_000_000 * 4` in TaikoL2. // We use 8x rather than 4x here to handle the scenario where the average number of // Taiko blocks proposed per Ethereum block is smaller than 1. // There is 250_000 additional gas for the anchor tx. Therefore, on explorers, you'll // read Taiko's gas limit to be 240_250_000. blockMaxGasLimit: 240_000_000, livenessBond: 125e18, // 125 Taiko token stateRootSyncInternal: 16, checkEOAForCalldataDA: true }); } /// @dev chain_pauser is supposed to be a cold wallet. function _authorizePause( address, bool ) internal view virtual override onlyFromOwnerOrNamed(LibStrings.B_CHAIN_WATCHDOG) { } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import "./AddressResolver.sol"; import "../libs/LibNetwork.sol"; /// @title EssentialContract /// @custom:security-contact [email protected] abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, AddressResolver { uint8 private constant _FALSE = 1; uint8 private constant _TRUE = 2; /// @dev The slot in transient storage of the reentry lock. /// This is the result of keccak256("ownerUUPS.reentry_slot") plus 1. The addition aims to /// prevent hash collisions with slots defined in EIP-1967, where slots are derived by /// keccak256("something") - 1, and with slots in SignalService, calculated directly with /// keccak256("something"). bytes32 private constant _REENTRY_SLOT = 0xa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b; /// @dev Slot 1. uint8 private __reentry; uint8 private __paused; uint64 public lastUnpausedAt; uint256[49] private __gap; /// @notice Emitted when the contract is paused. /// @param account The account that paused the contract. event Paused(address account); /// @notice Emitted when the contract is unpaused. /// @param account The account that unpaused the contract. event Unpaused(address account); error INVALID_PAUSE_STATUS(); error FUNC_NOT_IMPLEMENTED(); error REENTRANT_CALL(); error ZERO_ADDRESS(); error ZERO_VALUE(); /// @dev Modifier that ensures the caller is the owner or resolved address of a given name. /// @param _name The name to check against. modifier onlyFromOwnerOrNamed(bytes32 _name) { if (msg.sender != owner() && msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); _; } modifier notImplemented() { revert FUNC_NOT_IMPLEMENTED(); _; } modifier nonReentrant() { if (_loadReentryLock() == _TRUE) revert REENTRANT_CALL(); _storeReentryLock(_TRUE); _; _storeReentryLock(_FALSE); } modifier whenPaused() { if (!paused()) revert INVALID_PAUSE_STATUS(); _; } modifier whenNotPaused() { if (paused()) revert INVALID_PAUSE_STATUS(); _; } modifier nonZeroAddr(address _addr) { if (_addr == address(0)) revert ZERO_ADDRESS(); _; } modifier nonZeroValue(bytes32 _value) { if (_value == 0) revert ZERO_VALUE(); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @notice Pauses the contract. function pause() public virtual { _pause(); // We call the authorize function here to avoid: // Warning (5740): Unreachable code. _authorizePause(msg.sender, true); } /// @notice Unpauses the contract. function unpause() public virtual { _unpause(); // We call the authorize function here to avoid: // Warning (5740): Unreachable code. _authorizePause(msg.sender, false); } function impl() public view returns (address) { return _getImplementation(); } /// @notice Returns true if the contract is paused, and false otherwise. /// @return true if paused, false otherwise. function paused() public view returns (bool) { return __paused == _TRUE; } function inNonReentrant() public view returns (bool) { return _loadReentryLock() == _TRUE; } /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _addressManager The address of the {AddressManager} contract. function __Essential_init( address _owner, address _addressManager ) internal nonZeroAddr(_addressManager) { __Essential_init(_owner); __AddressResolver_init(_addressManager); } function __Essential_init(address _owner) internal virtual onlyInitializing { __Context_init(); _transferOwnership(_owner == address(0) ? msg.sender : _owner); __paused = _FALSE; } function _pause() internal whenNotPaused { __paused = _TRUE; emit Paused(msg.sender); } function _unpause() internal whenPaused { __paused = _FALSE; lastUnpausedAt = uint64(block.timestamp); emit Unpaused(msg.sender); } function _authorizeUpgrade(address) internal virtual override onlyOwner { } function _authorizePause(address, bool) internal virtual onlyOwner { } // Stores the reentry lock function _storeReentryLock(uint8 _reentry) internal virtual { if (LibNetwork.isDencunSupported(block.chainid)) { assembly { tstore(_REENTRY_SLOT, _reentry) } } else { __reentry = _reentry; } } // Loads the reentry lock function _loadReentryLock() internal view virtual returns (uint8 reentry_) { if (LibNetwork.isDencunSupported(block.chainid)) { assembly { reentry_ := tload(_REENTRY_SLOT) } } else { reentry_ = __reentry; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "../../libs/LibAddress.sol"; import "../../libs/LibNetwork.sol"; import "./LibUtils.sol"; /// @title LibProposing /// @notice A library for handling block proposals in the Taiko protocol. /// @custom:security-contact [email protected] library LibProposing { using LibAddress for address; // = keccak256(abi.encode(new TaikoData.EthDeposit[](0))) bytes32 private constant _EMPTY_ETH_DEPOSIT_HASH = 0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd; // 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_SIG(); error L1_LIVENESS_BOND_NOT_RECEIVED(); error L1_TOO_MANY_BLOCKS(); error L1_UNEXPECTED_PARENT(); /// @dev Proposes a Taiko L2 block. /// @param _state Current TaikoData.State. /// @param _tko The taiko token. /// @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, TaikoToken _tko, TaikoData.Config memory _config, IAddressResolver _resolver, bytes calldata _data, bytes calldata _txList ) internal returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_) { TaikoData.BlockParams memory params = abi.decode(_data, (TaikoData.BlockParams)); if (params.coinbase == address(0)) { params.coinbase = msg.sender; } // Taiko, as a Based Rollup, enables permissionless block proposals. TaikoData.SlotB memory b = _state.slotB; // It's essential to ensure that the ring buffer for proposed blocks // still has space for at least one more block. if (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 ( _config.checkEOAForCalldataDA && 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)); { ITierRouter tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false)); ITierProvider tierProvider = ITierProvider(tierRouter.getProvider(b.numBlocks)); // Use the difficulty as a random number meta_.minTier = tierProvider.getMinTier(uint256(meta_.difficulty)); } // Create the block that will be stored onchain TaikoData.Block memory blk = TaikoData.Block({ metaHash: LibUtils.hashMetadata(meta_), // Safeguard the liveness bond to ensure its preservation, // particularly in scenarios where it might be altered after the // block's proposal but before it has been proven or verified. assignedProver: address(0), livenessBond: _config.livenessBond, blockId: b.numBlocks, proposedAt: meta_.timestamp, proposedIn: uint64(block.number), // For a new block, the next transition ID is always 1, not 0. nextTransitionId: 1, // For unverified block, its verifiedTransitionId is always 0. verifiedTransitionId: 0 }); // Store the block in the ring buffer _state.blocks[b.numBlocks % _config.blockRingBufferSize] = blk; // Increment the counter (cursor) by 1. unchecked { ++_state.slotB.numBlocks; } _tko.transferFrom(msg.sender, address(this), _config.livenessBond); // Bribe the block builder. Unlock 1559-tips, this tip is only made // if this transaction succeeds. if (msg.value != 0 && block.coinbase != address(0)) { address(block.coinbase).sendEtherAndVerify(msg.value); } deposits_ = new TaikoData.EthDeposit[](0); emit BlockProposed({ blockId: meta_.id, assignedProver: msg.sender, livenessBond: _config.livenessBond, meta: meta_, depositsProcessed: deposits_ }); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../../verifiers/IVerifier.sol"; import "./LibUtils.sol"; /// @title LibProving /// @notice A library for handling block contestation and proving in the Taiko /// protocol. /// @custom:security-contact [email protected] library LibProving { using LibMath for uint256; // A struct to get around stack too deep issue and to cache state variables for multiple reads. struct Local { TaikoData.SlotB b; ITierProvider.Tier tier; ITierProvider.Tier minTier; TaikoToken tko; bytes32 metaHash; address assignedProver; bytes32 stateRoot; 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 _tko The taiko token. /// @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. function proveBlock( TaikoData.State storage _state, TaikoToken _tko, TaikoData.Config memory _config, IAddressResolver _resolver, TaikoData.BlockMetadata memory _meta, TaikoData.Transition memory _tran, TaikoData.TierProof memory _proof ) internal { // 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.tko = _tko; 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; if (LibUtils.shouldSyncStateRoot(_config.stateRootSyncInternal, local.blockId)) { local.stateRoot = _tran.stateRoot; } local.assignedProver = blk.assignedProver; if (local.assignedProver == address(0)) { local.assignedProver = _meta.sender; } local.livenessBond = blk.livenessBond; local.metaHash = blk.metaHash; // Check the integrity of the block data. It's worth noting that in // theory, this check may be skipped, but it's included for added // caution. if (local.blockId != _meta.id || local.metaHash != LibUtils.hashMetadata(_meta)) { revert L1_BLOCK_MISMATCH(); } // Each transition is uniquely identified by the parentHash, with the // blockHash and stateRoot open for later updates as higher-tier proofs // become available. In cases where a transition with the specified // parentHash does not exist, the transition ID (tid) will be set to 0. TaikoData.TransitionState memory ts; (local.tid, ts) = _fetchOrCreateTransition(_state, blk, _tran, local); // The new proof must meet or exceed the minimum tier required by the // block or the previous proof; it cannot be on a lower tier. if (_proof.tier == 0 || _proof.tier < _meta.minTier || _proof.tier < ts.tier) { revert L1_INVALID_TIER(); } // Retrieve the tier configurations. If the tier is not supported, the // subsequent action will result in a revert. { ITierRouter tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false)); ITierProvider tierProvider = ITierProvider(tierRouter.getProvider(local.blockId)); local.tier = tierProvider.getTier(_proof.tier); local.minTier = tierProvider.getTier(_meta.minTier); } local.inProvingWindow = !LibUtils.isPostDeadline({ _tsTimestamp: ts.timestamp, _lastUnpausedAt: local.b.lastUnpausedAt, _windowMinutes: local.minTier.provingWindow }); // Checks if only the assigned prover is permissioned to prove the block. // The assigned prover is granted exclusive permission to prove only the first // transition. if ( local.tier.contestBond != 0 && ts.contester == address(0) && local.tid == 1 && ts.tier == 0 && local.inProvingWindow ) { if (msg.sender != local.assignedProver) revert L1_NOT_ASSIGNED_PROVER(); } // We must verify the proof, and any failure in proof verification will // result in a revert. // // It's crucial to emphasize that the proof can be assessed in two // potential modes: "proving mode" and "contesting mode." However, the // precise verification logic is defined within each tier's IVerifier // contract implementation. We simply specify to the verifier contract // which mode it should utilize - if the new tier is higher than the // previous tier, we employ the proving mode; otherwise, we employ the // contesting mode (the new tier cannot be lower than the previous tier, // this has been checked above). // // It's obvious that proof verification is entirely decoupled from // Taiko's core protocol. if (local.tier.verifierName != "") { address verifier = _resolver.resolve(local.tier.verifierName, false); bool isContesting = _proof.tier == ts.tier && local.tier.contestBond != 0; IVerifier.Context memory ctx = IVerifier.Context({ metaHash: local.metaHash, blobHash: _meta.blobHash, // Separate msgSender to allow the prover to be any address in the future. prover: msg.sender, msgSender: msg.sender, blockId: local.blockId, isContesting: isContesting, blobUsed: _meta.blobUsed }); IVerifier(verifier).verifyProof(ctx, _tran, _proof); } local.isTopTier = local.tier.contestBond == 0; local.sameTransition = _tran.blockHash == ts.blockHash && local.stateRoot == ts.stateRoot; if (_proof.tier > ts.tier) { // Handles the case when an incoming tier is higher than the current transition's tier. // Reverts when the incoming proof tries to prove the same transition // (L1_ALREADY_PROVED). _overrideWithHigherProof(blk, ts, _tran, _proof, local); emit TransitionProved({ blockId: local.blockId, tran: _tran, prover: msg.sender, validityBond: local.tier.validityBond, tier: _proof.tier }); } else { // New transition and old transition on the same tier - and if this transaction tries to // prove the same, it reverts if (local.sameTransition) revert L1_ALREADY_PROVED(); if (local.isTopTier) { // The top tier prover re-proves. assert(local.tier.validityBond == 0); assert(ts.validityBond == 0 && ts.contester == address(0)); ts.prover = msg.sender; ts.blockHash = _tran.blockHash; ts.stateRoot = local.stateRoot; emit TransitionProved({ blockId: local.blockId, tran: _tran, prover: msg.sender, validityBond: 0, tier: _proof.tier }); } else { // Contesting but not on the highest tier if (ts.contester != address(0)) revert L1_ALREADY_CONTESTED(); // Making it a non-sliding window, relative when ts.timestamp was registered (or to // lastUnpaused if that one is bigger) if ( LibUtils.isPostDeadline( ts.timestamp, local.b.lastUnpausedAt, local.tier.cooldownWindow ) ) { revert L1_CANNOT_CONTEST(); } // _checkIfContestable(/*_state,*/ tier.cooldownWindow, ts.timestamp); // Burn the contest bond from the prover. _tko.transferFrom(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); _state.transitions[local.slot][local.tid] = ts; } /// @dev Handle the transition initialization logic function _fetchOrCreateTransition( TaikoData.State storage _state, TaikoData.Block storage _blk, TaikoData.Transition memory _tran, Local memory _local ) private returns (uint32 tid_, TaikoData.TransitionState memory ts_) { tid_ = LibUtils.getTransitionId(_state, _blk, _local.slot, _tran.parentHash); if (tid_ == 0) { // In cases where a transition with the provided parentHash is not // found, we must essentially "create" one and set it to its initial // state. This initial state can be viewed as a special transition // on tier-0. // // Subsequently, we transform this tier-0 transition into a // non-zero-tier transition with a proof. This approach ensures that // the same logic is applicable for both 0-to-non-zero transition // updates and non-zero-to-non-zero transition updates. unchecked { // Unchecked is safe: Not realistic 2**32 different fork choice // per block will be proven and none of them is valid tid_ = _blk.nextTransitionId++; } // Keep in mind that state.transitions are also reusable storage // slots, so it's necessary to reinitialize all transition fields // below. ts_.timestamp = _blk.proposedAt; if (tid_ == 1) { // This approach serves as a cost-saving technique for the // majority of blocks, where the first transition is expected to // be the correct one. Writing to `transitions` is more economical // since it resides in the ring buffer, whereas writing to // `transitionIds` is not as cost-effective. ts_.key = _tran.parentHash; // In the case of this first transition, the block's assigned // prover has the privilege to re-prove it, but only when the // assigned prover matches the previous prover. To ensure this, // we establish the transition's prover as the block's assigned // prover. Consequently, when we carry out a 0-to-non-zero // transition update, the previous prover will consistently be // the block's assigned prover. // // While alternative implementations are possible, introducing // such changes would require additional if-else logic. ts_.prover = _local.assignedProver; } else { // Furthermore, we index the transition for future retrieval. // It's worth emphasizing that this mapping for indexing is not // reusable. However, given that the majority of blocks will // only possess one transition — the correct one — we don't need // to be concerned about the cost in this case. // There is no need to initialize ts.key here because it's only used when tid == 1 _state.transitionIds[_local.blockId][_tran.parentHash] = tid_; } } else { // A transition with the provided parentHash has been located. ts_ = _state.transitions[_local.slot][tid_]; } } /// @dev Handles what happens when either the first transition is being proven or there is a /// higher tier proof incoming /// /// Assume Alice is the initial prover, Bob is the contester, and Cindy is the subsequent /// prover. The validity bond `V` is set at 100, and the contestation bond `C` at 500. If Bob /// successfully contests, he receives a reward of 65.625, calculated as 3/4 of 7/8 of 100. Cindy /// receives 21.875, which is 1/4 of 7/8 of 100, while the protocol retains 12.5 as friction. /// Bob's Return on Investment (ROI) is 13.125%, calculated from 65.625 divided by 500. // To establish the expected ROI `r` for valid contestations, where the contestation bond `C` to // validity bond `V` ratio is `C/V = 21/(32*r)`, and if `r` set at 10%, the C/V ratio will be // 6.5625. function _overrideWithHigherProof( TaikoData.Block storage _blk, TaikoData.TransitionState memory _ts, TaikoData.Transition memory _tran, TaikoData.TierProof memory _proof, Local memory _local ) private { // Higher tier proof overwriting lower tier proof uint256 reward; // reward to the new (current) prover if (_ts.contester != address(0)) { if (_local.sameTransition) { // The contested transition is proven to be valid, contester loses the game reward = _rewardAfterFriction(_ts.contestBond); // We return the validity bond back, but the original prover doesn't get any reward. _local.tko.transfer(_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; _local.tko.transfer(_ts.contester, _ts.contestBond + reward * 3); } } else { if (_local.sameTransition) revert L1_ALREADY_PROVED(); // The code below will be executed if // - 1) the transition is proved for the fist time, or // - 2) the transition is contested. reward = _rewardAfterFriction(_ts.validityBond); if (_local.livenessBond != 0) { // After the first proof, the block's liveness bond will always be reset to 0. // This means liveness bond will be handled only once for any given block. _blk.livenessBond = 0; if (_returnLivenessBond(_local, _proof.data)) { if (_local.assignedProver == msg.sender) { reward += _local.livenessBond; } else { _local.tko.transfer(_local.assignedProver, _local.livenessBond); } } } } unchecked { if (reward > _local.tier.validityBond) { _local.tko.transfer(msg.sender, reward - _local.tier.validityBond); } else if (reward < _local.tier.validityBond) { _local.tko.transferFrom( msg.sender, address(this), _local.tier.validityBond - reward ); } } _ts.validityBond = _local.tier.validityBond; _ts.contester = address(0); _ts.prover = msg.sender; _ts.tier = _proof.tier; if (!_local.sameTransition) { _ts.blockHash = _tran.blockHash; _ts.stateRoot = _local.stateRoot; } } /// @dev Returns the reward after applying 12.5% friction. function _rewardAfterFriction(uint256 _amount) private pure returns (uint256) { return _amount == 0 ? 0 : (_amount * 7) >> 3; } /// @dev Returns if the liveness bond shall be returned. function _returnLivenessBond( Local memory _local, bytes memory _proofData ) private pure returns (bool) { return _local.inProvingWindow && _local.tid == 1 || _local.isTopTier && _proofData.length == 32 && bytes32(_proofData) == LibStrings.H_RETURN_LIVENESS_BOND; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../../signal/ISignalService.sol"; import "./LibUtils.sol"; /// @title LibVerifying /// @notice A library for handling block verification in the Taiko protocol. /// @custom:security-contact [email protected] library LibVerifying { using LibMath for uint256; struct Local { TaikoData.SlotB b; uint64 blockId; uint64 slot; uint64 numBlocksVerified; uint32 tid; uint32 lastVerifiedTransitionId; uint16 tier; bytes32 blockHash; bytes32 syncStateRoot; uint64 syncBlockId; uint32 syncTransitionId; address prover; ITierRouter tierRouter; } // Warning: Any errors defined here must also be defined in TaikoErrors.sol. error L1_BATCH_TRANSFER_FAILED(); error L1_BLOCK_MISMATCH(); error L1_INVALID_CONFIG(); error L1_TRANSITION_ID_ZERO(); error L1_TOO_LATE(); /// @dev Verifies up to N blocks. function verifyBlocks( TaikoData.State storage _state, TaikoToken _tko, TaikoData.Config memory _config, IAddressResolver _resolver, uint64 _maxBlocksToVerify ) internal { if (_maxBlocksToVerify == 0) { return; } Local memory local; local.b = _state.slotB; local.blockId = local.b.lastVerifiedBlockId; local.slot = local.blockId % _config.blockRingBufferSize; TaikoData.Block storage blk = _state.blocks[local.slot]; if (blk.blockId != local.blockId) revert L1_BLOCK_MISMATCH(); local.lastVerifiedTransitionId = blk.verifiedTransitionId; local.tid = local.lastVerifiedTransitionId; // The following scenario should never occur but is included as a // precaution. if (local.tid == 0) revert L1_TRANSITION_ID_ZERO(); // The `blockHash` variable represents the most recently trusted // blockHash on L2. local.blockHash = _state.transitions[local.slot][local.tid].blockHash; // Unchecked is safe: // - assignment is within ranges // - blockId and numBlocksVerified values incremented will still be OK in the // next 584K years if we verifying one block per every second address[] memory provers = new address[](_maxBlocksToVerify); uint256[] memory bonds = new uint256[](_maxBlocksToVerify); unchecked { ++local.blockId; while ( local.blockId < local.b.numBlocks && local.numBlocksVerified < _maxBlocksToVerify ) { local.slot = local.blockId % _config.blockRingBufferSize; blk = _state.blocks[local.slot]; if (blk.blockId != local.blockId) revert L1_BLOCK_MISMATCH(); local.tid = LibUtils.getTransitionId(_state, blk, local.slot, local.blockHash); // When `tid` is 0, it indicates that there is no proven // transition with its parentHash equal to the blockHash of the // most recently verified block. if (local.tid == 0) break; // A transition with the correct `parentHash` has been located. TaikoData.TransitionState storage ts = _state.transitions[local.slot][local.tid]; // It's not possible to verify this block if either the // transition is contested and awaiting higher-tier proof or if // the transition is still within its cooldown period. local.tier = ts.tier; if (ts.contester != address(0)) { break; } else { if (local.tierRouter == ITierRouter(address(0))) { local.tierRouter = ITierRouter(_resolver.resolve(LibStrings.B_TIER_ROUTER, false)); } uint24 cooldown = ITierProvider(local.tierRouter.getProvider(local.blockId)) .getTier(local.tier).cooldownWindow; if (!LibUtils.isPostDeadline(ts.timestamp, local.b.lastUnpausedAt, cooldown)) { // If cooldownWindow is 0, the block can theoretically // be proved and verified within the same L1 block. break; } } // Update variables local.lastVerifiedTransitionId = local.tid; local.blockHash = ts.blockHash; local.prover = ts.prover; provers[local.numBlocksVerified] = local.prover; bonds[local.numBlocksVerified] = ts.validityBond; // Note: We exclusively address the bonds linked to the // transition used for verification. While there may exist // other transitions for this block, we disregard them entirely. // The bonds for these other transitions are burned (more precisely held in custody) // either when the transitions are generated or proven. In such cases, both the // provers and contesters of those transitions forfeit their bonds. emit LibUtils.BlockVerified({ blockId: local.blockId, prover: local.prover, blockHash: local.blockHash, stateRoot: 0, // DEPRECATED and is always zero. tier: local.tier }); if (LibUtils.shouldSyncStateRoot(_config.stateRootSyncInternal, local.blockId)) { bytes32 stateRoot = ts.stateRoot; if (stateRoot != 0) { local.syncStateRoot = stateRoot; local.syncBlockId = local.blockId; local.syncTransitionId = local.tid; } } ++local.blockId; ++local.numBlocksVerified; } if (local.numBlocksVerified != 0) { uint64 lastVerifiedBlockId = local.b.lastVerifiedBlockId + local.numBlocksVerified; local.slot = lastVerifiedBlockId % _config.blockRingBufferSize; _state.slotB.lastVerifiedBlockId = lastVerifiedBlockId; _state.blocks[local.slot].verifiedTransitionId = local.lastVerifiedTransitionId; // Resize the provers and bonds array uint256 newLen = local.numBlocksVerified; assembly { mstore(provers, newLen) mstore(bonds, newLen) } if (!_tko.batchTransfer(provers, bonds)) revert L1_BATCH_TRANSFER_FAILED(); if (local.syncStateRoot != 0) { _state.slotA.lastSyncedBlockId = local.syncBlockId; _state.slotA.lastSynecdAt = uint64(block.timestamp); // We write the synced block's verifiedTransitionId to storage if (local.syncBlockId != lastVerifiedBlockId) { local.slot = local.syncBlockId % _config.blockRingBufferSize; _state.blocks[local.slot].verifiedTransitionId = local.syncTransitionId; } // Ask signal service to write cross chain signal ISignalService(_resolver.resolve(LibStrings.B_SIGNAL_SERVICE, false)) .syncChainData( _config.chainId, LibStrings.H_STATE_ROOT, local.syncBlockId, local.syncStateRoot ); } } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./TaikoData.sol"; /// @title ITaikoL1 /// @custom:security-contact [email protected] interface ITaikoL1 { /// @notice Proposes a Taiko L2 block. /// @param _params Block parameters, currently an encoded BlockParams object. /// @param _txList txList data if calldata is used for DA. /// @return meta_ The metadata of the proposed L2 block. /// @return deposits_ The Ether deposits processed. function proposeBlock( bytes calldata _params, bytes calldata _txList ) external payable returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_); /// @notice Proves or contests a block transition. /// @param _blockId The index of the block to prove. This is also used to /// select the right implementation version. /// @param _input An abi-encoded (TaikoData.BlockMetadata, TaikoData.Transition, /// TaikoData.TierProof) tuple. function proveBlock(uint64 _blockId, bytes calldata _input) external; /// @notice Verifies up to a certain number of blocks. /// @param _maxBlocksToVerify Max number of blocks to verify. function verifyBlocks(uint64 _maxBlocksToVerify) external; /// @notice Pause block proving. /// @param _pause True if paused. function pauseProving(bool _pause) external; /// @notice Gets the configuration of the TaikoL1 contract. /// @return Config struct containing configuration parameters. function getConfig() external pure returns (TaikoData.Config memory); }
// SPDX-License-Identifier: MIT 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_BATCH_TRANSFER_FAILED(); 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_PARAM(); error L1_INVALID_PAUSE_STATUS(); 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_NO_HOOKS(); error L1_PROVING_PAUSED(); error L1_RECEIVE_DISABLED(); error L1_TOO_LATE(); error L1_TOO_MANY_BLOCKS(); error L1_TRANSITION_ID_ZERO(); error L1_TRANSITION_NOT_FOUND(); 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 Deprecated and is always zero. /// @param tier The tier ID of the proof. event BlockVerified( uint256 indexed blockId, address indexed prover, bytes32 blockHash, bytes32 stateRoot, uint16 tier ); /// @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822.sol"; import "../ERC1967/ERC1967Upgrade.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "./IAddressManager.sol"; import "./IAddressResolver.sol"; /// @title AddressResolver /// @notice See the documentation in {IAddressResolver}. /// @custom:security-contact [email protected] abstract contract AddressResolver is IAddressResolver, Initializable { /// @notice Address of the AddressManager. address public addressManager; uint256[49] private __gap; error RESOLVER_DENIED(); error RESOLVER_INVALID_MANAGER(); error RESOLVER_UNEXPECTED_CHAINID(); error RESOLVER_ZERO_ADDR(uint64 chainId, bytes32 name); /// @dev Modifier that ensures the caller is the resolved address of a given /// name. /// @param _name The name to check against. modifier onlyFromNamed(bytes32 _name) { if (msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); _; } /// @dev Modifier that ensures the caller is a resolved address to either _name1 or _name2 /// name. /// @param _name1 The first name to check against. /// @param _name2 The second name to check against. modifier onlyFromNamedEither(bytes32 _name1, bytes32 _name2) { if (msg.sender != resolve(_name1, true) && msg.sender != resolve(_name2, true)) { revert RESOLVER_DENIED(); } _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @inheritdoc IAddressResolver function resolve( bytes32 _name, bool _allowZeroAddress ) public view virtual returns (address payable) { return _resolve(uint64(block.chainid), _name, _allowZeroAddress); } /// @inheritdoc IAddressResolver function resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) public view virtual returns (address payable) { return _resolve(_chainId, _name, _allowZeroAddress); } /// @dev Initialization method for setting up AddressManager reference. /// @param _addressManager Address of the AddressManager. function __AddressResolver_init(address _addressManager) internal virtual onlyInitializing { if (block.chainid > type(uint64).max) { revert RESOLVER_UNEXPECTED_CHAINID(); } addressManager = _addressManager; } /// @dev Helper method to resolve name-to-address. /// @param _chainId The chainId of interest. /// @param _name Name whose address is to be resolved. /// @param _allowZeroAddress If set to true, does not throw if the resolved /// address is `address(0)`. /// @return addr_ Address associated with the given name on the specified /// chain. function _resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) private view returns (address payable addr_) { address _addressManager = addressManager; if (_addressManager == address(0)) revert RESOLVER_INVALID_MANAGER(); addr_ = payable(IAddressManager(_addressManager).getAddress(_chainId, _name)); if (!_allowZeroAddress && addr_ == address(0)) { revert RESOLVER_ZERO_ADDR(_chainId, _name); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibNetwork library LibNetwork { uint256 internal constant MAINNET = 1; uint256 internal constant ROPSTEN = 2; uint256 internal constant RINKEBY = 4; uint256 internal constant GOERLI = 5; uint256 internal constant KOVAN = 42; uint256 internal constant HOLESKY = 17_000; uint256 internal constant SEPOLIA = 11_155_111; uint64 internal constant TAIKO = 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 isTaikoDevnet(uint256 _chainId) internal pure returns (bool) { return _chainId >= 32_300 && _chainId <= 32_400; } /// @dev Checks if the chain supports Dencun hardfork. Note that this check doesn't need to be /// exhaustive. /// @param _chainId The chain ID. /// @return true if the chain supports Dencun hardfork, false otherwise. function isDencunSupported(uint256 _chainId) internal pure returns (bool) { return _chainId == LibNetwork.MAINNET || _chainId == LibNetwork.HOLESKY || _chainId == LibNetwork.SEPOLIA || isTaikoDevnet(_chainId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "@openzeppelin/contracts/interfaces/IERC1271.sol"; /// @title LibAddress /// @dev Provides utilities for address-related operations. /// @custom:security-contact [email protected] library LibAddress { error ETH_TRANSFER_FAILED(); /// @dev Sends Ether to the specified address. This method will not revert even if sending ether /// fails. /// This function is inspired by /// https://github.com/nomad-xyz/ExcessivelySafeCall/blob/main/src/ExcessivelySafeCall.sol /// @param _to The recipient address. /// @param _amount The amount of Ether to send in wei. /// @param _gasLimit The max amount gas to pay for this transaction. /// @return success_ true if the call is successful, false otherwise. function sendEther( address _to, uint256 _amount, uint256 _gasLimit, bytes memory _calldata ) internal returns (bool success_) { // Check for zero-address transactions if (_to == address(0)) revert ETH_TRANSFER_FAILED(); // dispatch message to recipient // by assembly calling "handle" function // we call via assembly to avoid memcopying a very large returndata // returned by a malicious contract assembly { success_ := call( _gasLimit, // gas _to, // recipient _amount, // ether value add(_calldata, 0x20), // inloc mload(_calldata), // inlen 0, // outloc 0 // outlen ) } } /// @dev Sends Ether to the specified address. This method will revert if sending ether fails. /// @param _to The recipient address. /// @param _amount The amount of Ether to send in wei. /// @param _gasLimit The max amount gas to pay for this transaction. function sendEtherAndVerify(address _to, uint256 _amount, uint256 _gasLimit) internal { if (_amount == 0) return; if (!sendEther(_to, _amount, _gasLimit, "")) { revert ETH_TRANSFER_FAILED(); } } /// @dev Sends Ether to the specified address. This method will revert if sending ether fails. /// @param _to The recipient address. /// @param _amount The amount of Ether to send in wei. function sendEtherAndVerify(address _to, uint256 _amount) internal { sendEtherAndVerify(_to, _amount, gasleft()); } function supportsInterface( address _addr, bytes4 _interfaceId ) internal view returns (bool result_) { if (!Address.isContract(_addr)) return false; try IERC165(_addr).supportsInterface(_interfaceId) returns (bool _result) { result_ = _result; } catch { } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../../common/IAddressResolver.sol"; import "../../common/LibStrings.sol"; import "../../tko/TaikoToken.sol"; import "../../libs/LibMath.sol"; import "../tiers/ITierProvider.sol"; import "../tiers/ITierRouter.sol"; import "../TaikoData.sol"; /// @title LibUtils /// @notice A library that offers helper functions. /// @custom:security-contact [email protected] library LibUtils { using LibMath for uint256; /// @dev Emitted when a block is verified. /// @param blockId The ID of the verified block. /// @param prover The prover whose transition is used for verifying the /// block. /// @param blockHash The hash of the verified block. /// @param stateRoot Deprecated and is always zero. /// @param tier The tier ID of the proof. event BlockVerified( uint256 indexed blockId, address indexed prover, bytes32 blockHash, bytes32 stateRoot, uint16 tier ); // Warning: Any errors defined here must also be defined in TaikoErrors.sol. error L1_BLOCK_MISMATCH(); error L1_INVALID_BLOCK_ID(); error L1_INVALID_GENESIS_HASH(); error L1_TRANSITION_NOT_FOUND(); error L1_UNEXPECTED_TRANSITION_ID(); /// @notice Initializes the Taiko protocol state. /// @param _state The state to initialize. /// @param _genesisBlockHash The block hash of the genesis block. function init(TaikoData.State storage _state, bytes32 _genesisBlockHash) internal { if (_genesisBlockHash == 0) revert L1_INVALID_GENESIS_HASH(); // Init state _state.slotA.genesisHeight = uint64(block.number); _state.slotA.genesisTimestamp = uint64(block.timestamp); _state.slotB.numBlocks = 1; // Init the genesis block TaikoData.Block storage blk = _state.blocks[0]; blk.nextTransitionId = 2; blk.proposedAt = uint64(block.timestamp); blk.verifiedTransitionId = 1; blk.metaHash = bytes32(uint256(1)); // Give the genesis metahash a non-zero value. // Init the first state transition TaikoData.TransitionState storage ts = _state.transitions[0][1]; ts.blockHash = _genesisBlockHash; ts.prover = address(0); ts.timestamp = uint64(block.timestamp); emit BlockVerified({ blockId: 0, prover: address(0), blockHash: _genesisBlockHash, stateRoot: 0, tier: 0 }); } /// @dev Retrieves a block based on its ID. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @return blk_ The block storage pointer. /// @return slot_ The slot value. function getBlock( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId ) internal view returns (TaikoData.Block storage blk_, uint64 slot_) { slot_ = _blockId % _config.blockRingBufferSize; blk_ = _state.blocks[slot_]; if (blk_.blockId != _blockId) revert L1_INVALID_BLOCK_ID(); } /// @dev Retrieves a block's block hash and state root. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @return blockHash_ The block's block hash. /// @return stateRoot_ The block's storage root. function getBlockInfo( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId ) internal view returns (bytes32 blockHash_, bytes32 stateRoot_) { (TaikoData.Block storage blk, uint64 slot) = getBlock(_state, _config, _blockId); if (blk.verifiedTransitionId != 0) { TaikoData.TransitionState storage transition = _state.transitions[slot][blk.verifiedTransitionId]; blockHash_ = transition.blockHash; stateRoot_ = transition.stateRoot; } } /// @notice This function will revert if the transition is not found. /// @dev Retrieves the transition with a given parentHash. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @param _tid The transition id. /// @return The state transition pointer. function getTransition( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId, uint32 _tid ) internal view returns (TaikoData.TransitionState storage) { (TaikoData.Block storage blk, uint64 slot) = getBlock(_state, _config, _blockId); if (_tid == 0 || _tid >= blk.nextTransitionId) revert L1_TRANSITION_NOT_FOUND(); return _state.transitions[slot][_tid]; } /// @notice This function will revert if the transition is not found. /// @dev Retrieves the transition with a given parentHash. /// @param _state Current TaikoData.State. /// @param _config Actual TaikoData.Config. /// @param _blockId Id of the block. /// @param _parentHash Parent hash of the block. /// @return The state transition pointer. function getTransition( TaikoData.State storage _state, TaikoData.Config memory _config, uint64 _blockId, bytes32 _parentHash ) internal view returns (TaikoData.TransitionState storage) { (TaikoData.Block storage blk, uint64 slot) = getBlock(_state, _config, _blockId); uint32 tid = getTransitionId(_state, blk, slot, _parentHash); if (tid == 0) revert L1_TRANSITION_NOT_FOUND(); return _state.transitions[slot][tid]; } /// @dev Retrieves the ID of the transition with a given parentHash. /// This function will return 0 if the transition is not found. function getTransitionId( TaikoData.State storage _state, TaikoData.Block storage _blk, uint64 _slot, bytes32 _parentHash ) internal view returns (uint32 tid_) { if (_state.transitions[_slot][1].key == _parentHash) { tid_ = 1; if (tid_ >= _blk.nextTransitionId) revert L1_UNEXPECTED_TRANSITION_ID(); } else { tid_ = _state.transitionIds[_blk.blockId][_parentHash]; if (tid_ != 0 && tid_ >= _blk.nextTransitionId) revert L1_UNEXPECTED_TRANSITION_ID(); } } function isPostDeadline( uint256 _tsTimestamp, uint256 _lastUnpausedAt, uint256 _windowMinutes ) internal view returns (bool) { unchecked { uint256 deadline = _tsTimestamp.max(_lastUnpausedAt) + _windowMinutes * 60; return block.timestamp >= deadline; } } function shouldVerifyBlocks( TaikoData.Config memory _config, uint64 _blockId, bool _isBlockProposed ) internal pure returns (bool) { if (_config.maxBlocksToVerify == 0) return false; // Consider each segment of 8 blocks, verification is attempted either on block 3 if it has // been // proved, or on block 7 if it has been proposed. Over time, the ratio of blocks to // verification attempts averages 4:1, meaning each verification attempt typically covers 4 // blocks. However, considering worst cases caused by blocks being proved out of order, some // verification attempts may verify few or no blocks. In such cases, additional // verifications are needed to catch up. Consequently, the `maxBlocksToVerify` parameter // should be set high enough, for example 16, to allow for efficient catch-up. // Now lets use `maxBlocksToVerify` as an input to calculate the size of each block // segment, instead of using 8 as a constant. uint256 segmentSize = _config.maxBlocksToVerify >> 1; if (segmentSize <= 1) return true; return _blockId % segmentSize == (_isBlockProposed ? 0 : segmentSize >> 1); } function shouldSyncStateRoot( uint256 _stateRootSyncInternal, uint256 _blockId ) internal pure returns (bool) { if (_stateRootSyncInternal <= 1) return true; unchecked { // We could use `_blockId % _stateRootSyncInternal == 0`, but this will break many unit // tests as in most of these tests, we test block#1, so by setting // config._stateRootSyncInternal = 2, we can keep the tests unchanged. return _blockId % _stateRootSyncInternal == _stateRootSyncInternal - 1; } } function hashMetadata(TaikoData.BlockMetadata memory _meta) internal pure returns (bytes32) { return keccak256(abi.encode(_meta)); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../L1/TaikoData.sol"; /// @title IVerifier /// @notice Defines the function that handles proof verification. /// @custom:security-contact [email protected] interface IVerifier { struct Context { bytes32 metaHash; bytes32 blobHash; address prover; uint64 blockId; bool isContesting; bool blobUsed; address msgSender; } /// @notice Verifies a proof. /// @param _ctx The context of the proof verification. /// @param _tran The transition to verify. /// @param _proof The proof to verify. function verifyProof( Context calldata _ctx, TaikoData.Transition calldata _tran, TaikoData.TierProof calldata _proof ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title ISignalService /// @notice The SignalService contract serves as a secure cross-chain message /// passing system. It defines methods for sending and verifying signals with /// merkle proofs. The trust assumption is that the target chain has secure /// access to the merkle root (such as Taiko injects it in the anchor /// transaction). With this, verifying a signal is reduced to simply verifying /// a merkle proof. /// @custom:security-contact [email protected] interface ISignalService { enum CacheOption { CACHE_NOTHING, CACHE_SIGNAL_ROOT, CACHE_STATE_ROOT, CACHE_BOTH } struct HopProof { /// @notice This hop's destination chain ID. If there is a next hop, this ID is the next /// hop's source chain ID. uint64 chainId; /// @notice The ID of a source chain block whose state root has been synced to the hop's /// destination chain. /// Note that this block ID must be greater than or equal to the block ID where the signal /// was sent on the source chain. uint64 blockId; /// @notice The state root or signal root of the source chain at the above blockId. This /// value has been synced to the destination chain. /// @dev To get both the blockId and the rootHash, apps should subscribe to the /// ChainDataSynced event or query `topBlockId` first using the source chain's ID and /// LibStrings.H_STATE_ROOT to get the most recent block ID synced, then call /// `getSyncedChainData` to read the synchronized data. bytes32 rootHash; /// @notice Options to cache either the state roots or signal roots of middle-hops to the /// current chain. CacheOption cacheOption; /// @notice The signal service's account proof. If this value is empty, then `rootHash` will /// be used as the signal root, otherwise, `rootHash` will be used as the state root. bytes[] accountProof; /// @notice The signal service's storage proof. bytes[] storageProof; } /// @notice Emitted when a remote chain's state root or signal root is /// synced locally as a signal. /// @param chainId The remote chainId. /// @param blockId The chain data's corresponding blockId. /// @param kind A value to mark the data type. /// @param data The remote data. /// @param signal The signal for this chain data. event ChainDataSynced( uint64 indexed chainId, uint64 indexed blockId, bytes32 indexed kind, bytes32 data, bytes32 signal ); /// @notice Emitted when a signal is sent. /// @param app The address that initiated the signal. /// @param signal The signal (message) that was sent. /// @param slot The location in storage where this signal is stored. /// @param value The value of the signal. event SignalSent(address app, bytes32 signal, bytes32 slot, bytes32 value); /// @notice Emitted when an address is authorized or deauthorized. /// @param addr The address to be authorized or deauthorized. /// @param authorized True if authorized, false otherwise. event Authorized(address indexed addr, bool authorized); /// @notice Send a signal (message) by setting the storage slot to the same value as the signal /// itself. /// @param _signal The signal (message) to send. /// @return slot_ The location in storage where this signal is stored. function sendSignal(bytes32 _signal) external returns (bytes32 slot_); /// @notice Sync a data from a remote chain locally as a signal. The signal is calculated /// uniquely from chainId, kind, and data. /// @param _chainId The remote chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding blockId /// @param _chainData The remote data. /// @return signal_ The signal for this chain data. function syncChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) external returns (bytes32 signal_); /// @notice Verifies if a signal has been received on the target chain. /// @param _chainId The identifier for the source chain from which the /// signal originated. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) to send. /// @param _proof Merkle proof that the signal was persisted on the /// source chain. /// @return numCacheOps_ The number of newly cached items. function proveSignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external returns (uint256 numCacheOps_); /// @notice Verifies if a signal has been received on the target chain. /// This is the "readonly" version of proveSignalReceived. /// @param _chainId The identifier for the source chain from which the /// signal originated. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) to send. /// @param _proof Merkle proof that the signal was persisted on the /// source chain. function verifySignalReceived( uint64 _chainId, address _app, bytes32 _signal, bytes calldata _proof ) external view; /// @notice Verifies if a particular signal has already been sent. /// @param _app The address that initiated the signal. /// @param _signal The signal (message) that was sent. /// @return true if the signal has been sent, otherwise false. function isSignalSent(address _app, bytes32 _signal) external view returns (bool); /// @notice Checks if a chain data has been synced. /// @param _chainId The remote chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding blockId /// @param _chainData The remote data. /// @return true if the data has been synced, otherwise false. function isChainDataSynced( uint64 _chainId, bytes32 _kind, uint64 _blockId, bytes32 _chainData ) external view returns (bool); /// @notice Returns the given block's chain data. /// @param _chainId Identifier of the chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding block id. If this value is 0, use the top /// block id. /// @return blockId_ The actual block id. /// @return chainData_ The synced chain data. function getSyncedChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) external view returns (uint64 blockId_, bytes32 chainData_); /// @notice Returns the data to be used for caching slot generation. /// @param _chainId Identifier of the chainId. /// @param _kind A value to mark the data type. /// @param _blockId The chain data's corresponding block id. If this value is 0, use the top /// block id. /// @return signal_ The signal used for caching slot creation. function signalForChainData( uint64 _chainId, bytes32 _kind, uint64 _blockId ) external pure returns (bytes32 signal_); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title TaikoData /// @notice This library defines various data structures used in the Taiko /// protocol. /// @custom:security-contact [email protected] library TaikoData { /// @dev Struct holding Taiko configuration parameters. See {TaikoConfig}. struct Config { // --------------------------------------------------------------------- // Group 1: General configs // --------------------------------------------------------------------- // The chain ID of the network where Taiko contracts are deployed. uint64 chainId; // --------------------------------------------------------------------- // Group 2: Block level configs // --------------------------------------------------------------------- // The maximum number of proposals allowed in a single block. uint64 blockMaxProposals; // Size of the block ring buffer, allowing extra space for proposals. uint64 blockRingBufferSize; // The maximum number of verifications allowed when a block is proposed // or proved. uint64 maxBlocksToVerify; // The maximum gas limit allowed for a block. uint32 blockMaxGasLimit; // --------------------------------------------------------------------- // Group 3: Proof related configs // --------------------------------------------------------------------- // The amount of Taiko token as a prover liveness bond uint96 livenessBond; // --------------------------------------------------------------------- // Group 4: Cross-chain sync // --------------------------------------------------------------------- // The number of L2 blocks between each L2-to-L1 state root sync. uint8 stateRootSyncInternal; bool checkEOAForCalldataDA; } /// @dev 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; // DEPRECATED, value ignored. address coinbase; bytes32 extraData; bytes32 parentMetaHash; HookCall[] hookCalls; // DEPRECATED, value ignored. bytes signature; } /// @dev Struct containing data only required for proving a block /// Note: On L2, `block.difficulty` is the pseudo name of /// `block.prevrandao`, which returns a random number provided by the layer /// 1 chain. struct BlockMetadata { bytes32 l1Hash; bytes32 difficulty; bytes32 blobHash; //or txListHash (if Blob not yet supported) bytes32 extraData; bytes32 depositsHash; address coinbase; // L2 coinbase, uint64 id; uint32 gasLimit; uint64 timestamp; uint64 l1Height; uint16 minTier; bool blobUsed; bytes32 parentMetaHash; address sender; // a.k.a proposer } /// @dev Struct representing transition to be proven. struct Transition { bytes32 parentHash; bytes32 blockHash; bytes32 stateRoot; bytes32 graffiti; // Arbitrary data that the prover can use for various purposes. } /// @dev Struct representing state transition data. /// 6 slots used. struct TransitionState { bytes32 key; // slot 1, only written/read for the 1st state transition. bytes32 blockHash; // slot 2 bytes32 stateRoot; // slot 3 address prover; // slot 4 uint96 validityBond; address contester; // slot 5 uint96 contestBond; uint64 timestamp; // slot 6 (90 bits) uint16 tier; uint8 __reserved1; } /// @dev Struct containing data required for verifying a block. /// 3 slots used. struct Block { bytes32 metaHash; // slot 1 address assignedProver; // slot 2 uint96 livenessBond; uint64 blockId; // slot 3 uint64 proposedAt; // timestamp uint64 proposedIn; // L1 block number, required/used by node/client. uint32 nextTransitionId; // The ID of the transaction that is used to verify this block. However, if // this block is not verified as the last block in a batch, verifiedTransitionId // will remain zero. uint32 verifiedTransitionId; } /// @dev Struct representing an Ethereum deposit. /// 2 slot used. Currently removed from protocol, but to be backwards compatible, the struct and /// return values stayed for now. struct EthDeposit { address recipient; uint96 amount; uint64 id; } /// @dev Forge is only able to run coverage in case the contracts by default /// capable of compiling without any optimization (neither optimizer runs, /// no compiling --via-ir flag). /// In order to resolve stack too deep without optimizations, we needed to /// introduce outsourcing vars into structs below. struct SlotA { uint64 genesisHeight; uint64 genesisTimestamp; uint64 lastSyncedBlockId; uint64 lastSynecdAt; // typo! } struct SlotB { uint64 numBlocks; uint64 lastVerifiedBlockId; bool provingPaused; uint8 __reservedB1; uint16 __reservedB2; uint32 __reservedB3; uint64 lastUnpausedAt; } /// @dev Struct holding the state variables for the {TaikoL1} contract. struct State { // Ring buffer for proposed blocks and a some recent verified blocks. mapping(uint64 blockId_mod_blockRingBufferSize => Block blk) blocks; // Indexing to transition ids (ring buffer not possible) mapping(uint64 blockId => mapping(bytes32 parentHash => uint32 transitionId)) transitionIds; // Ring buffer for transitions mapping( uint64 blockId_mod_blockRingBufferSize => mapping(uint32 transitionId => TransitionState ts) ) transitions; // Ring buffer for Ether deposits bytes32 __reserve1; SlotA slotA; // slot 5 SlotB slotB; // slot 6 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 pragma solidity 0.8.24; /// @title IAddressResolver /// @notice This contract acts as a bridge for name-to-address resolution. /// It delegates the resolution to the AddressManager. By separating the logic, /// we can maintain flexibility in address management without affecting the /// resolving process. /// @dev Note that the address manager should be changed using upgradability, there /// is no setAddressManager() function to guarantee atomicity across all /// contracts that are resolvers. /// @custom:security-contact [email protected] interface IAddressResolver { /// @notice Resolves a name to its address deployed on this chain. /// @param _name Name whose address is to be resolved. /// @param _allowZeroAddress If set to true, does not throw if the resolved /// address is `address(0)`. /// @return Address associated with the given name. function resolve( bytes32 _name, bool _allowZeroAddress ) external view returns (address payable); /// @notice Resolves a name to its address deployed on a specified chain. /// @param _chainId The chainId of interest. /// @param _name Name whose address is to be resolved. /// @param _allowZeroAddress If set to true, does not throw if the resolved /// address is `address(0)`. /// @return Address associated with the given name on the specified /// chain. function resolve( uint64 _chainId, bytes32 _name, bool _allowZeroAddress ) external view returns (address payable); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibStrings /// @custom:security-contact [email protected] library LibStrings { bytes32 internal constant B_AUTOMATA_DCAP_ATTESTATION = bytes32("automata_dcap_attestation"); bytes32 internal constant B_BRIDGE = bytes32("bridge"); bytes32 internal constant B_BRIDGE_WATCHDOG = bytes32("bridge_watchdog"); bytes32 internal constant B_BRIDGED_ERC1155 = bytes32("bridged_erc1155"); bytes32 internal constant B_BRIDGED_ERC20 = bytes32("bridged_erc20"); bytes32 internal constant B_BRIDGED_ERC721 = bytes32("bridged_erc721"); bytes32 internal constant B_CHAIN_WATCHDOG = bytes32("chain_watchdog"); bytes32 internal constant B_ERC1155_VAULT = bytes32("erc1155_vault"); bytes32 internal constant B_ERC20_VAULT = bytes32("erc20_vault"); bytes32 internal constant B_ERC721_VAULT = bytes32("erc721_vault"); bytes32 internal constant B_PROVER_ASSIGNMENT = bytes32("PROVER_ASSIGNMENT"); bytes32 internal constant B_PROVER_SET = bytes32("prover_set"); bytes32 internal constant B_QUOTA_MANAGER = bytes32("quota_manager"); bytes32 internal constant B_SGX_WATCHDOG = bytes32("sgx_watchdog"); bytes32 internal constant B_SIGNAL_SERVICE = bytes32("signal_service"); bytes32 internal constant B_TAIKO = bytes32("taiko"); bytes32 internal constant B_TAIKO_TOKEN = bytes32("taiko_token"); bytes32 internal constant B_TIER_GUARDIAN = bytes32("tier_guardian"); bytes32 internal constant B_TIER_GUARDIAN_MINORITY = bytes32("tier_guardian_minority"); bytes32 internal constant B_TIER_ROUTER = bytes32("tier_router"); bytes32 internal constant B_TIER_SGX = bytes32("tier_sgx"); bytes32 internal constant B_TIER_SGX_ZKVM = bytes32("tier_sgx_zkvm"); bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer"); bytes32 internal constant H_RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND"); bytes32 internal constant H_SIGNAL_ROOT = keccak256("SIGNAL_ROOT"); bytes32 internal constant H_STATE_ROOT = keccak256("STATE_ROOT"); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./TaikoTokenBase.sol"; /// @title TaikoToken /// @notice The TaikoToken (TKO), in the protocol is used for prover collateral /// in the form of bonds. It is an ERC20 token with 18 decimal places of precision. /// @dev Labeled in AddressResolver as "taiko_token" /// @dev On Ethereum, this contract is deployed behind a proxy at /// 0x10dea67478c5F8C5E2D90e5E9B26dBe60c54d800 (token.taiko.eth) /// @custom:security-contact [email protected] contract TaikoToken is TaikoTokenBase { address private constant _TAIKO_L1 = 0x06a9Ab27c7e2255df1815E6CC0168d7755Feb19a; address private constant _ERC20_VAULT = 0x996282cA11E5DEb6B5D122CC3B9A1FcAAD4415Ab; error TT_INVALID_PARAM(); /// @notice Initializes the contract. /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _recipient The address to receive initial token minting. function init(address _owner, address _recipient) public initializer { __Essential_init(_owner); __ERC20_init("Taiko Token", "TKO"); __ERC20Votes_init(); __ERC20Permit_init("Taiko Token"); // Mint 1 billion tokens _mint(_recipient, 1_000_000_000 ether); } /// @notice Batch transfers tokens /// @param recipients The list of addresses to transfer tokens to. /// @param amounts The list of amounts for transfer. /// @return true if the transfer is successful. function batchTransfer( address[] calldata recipients, uint256[] calldata amounts ) external returns (bool) { if (recipients.length != amounts.length) revert TT_INVALID_PARAM(); for (uint256 i; i < recipients.length; ++i) { _transfer(msg.sender, recipients[i], amounts[i]); } return true; } function delegates(address account) public view virtual override returns (address) { // Special checks to avoid reading from storage slots if (account == _TAIKO_L1 || account == _ERC20_VAULT) return address(0); else return super.delegates(account); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title LibMath /// @dev This library offers additional math functions for uint256. /// @custom:security-contact [email protected] library LibMath { /// @dev Returns the smaller of the two given values. /// @param _a The first number to compare. /// @param _b The second number to compare. /// @return The smaller of the two numbers. function min(uint256 _a, uint256 _b) internal pure returns (uint256) { return _a > _b ? _b : _a; } /// @dev Returns the larger of the two given values. /// @param _a The first number to compare. /// @param _b The second number to compare. /// @return The larger of the two numbers. function max(uint256 _a, uint256 _b) internal pure returns (uint256) { return _a > _b ? _a : _b; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @title ITierProvider /// @notice Defines interface to return tier configuration. /// @custom:security-contact [email protected] interface ITierProvider { struct Tier { bytes32 verifierName; uint96 validityBond; uint96 contestBond; uint24 cooldownWindow; // in minutes uint16 provingWindow; // in minutes uint8 maxBlocksToVerifyPerProof; // DEPRECATED } error TIER_NOT_FOUND(); /// @dev Retrieves the configuration for a specified tier. /// @param tierId ID of the tier. /// @return Tier struct containing the tier's parameters. function getTier(uint16 tierId) external view returns (Tier memory); /// @dev Retrieves the IDs of all supported tiers. /// Note that the core protocol requires the number of tiers to be smaller /// than 256. In reality, this number should be much smaller. /// @return The ids of the tiers. function getTierIds() external view returns (uint16[] memory); /// @dev Determines the minimal tier for a block based on a random input. /// @param rand A pseudo-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 pragma solidity 0.8.24; /// @title ITierRouter /// @notice Defines interface to return an ITierProvider /// @custom:security-contact [email protected] interface ITierRouter { /// @dev Returns the address of the TierProvider for a given block. /// @param blockId ID of the block. /// @return The address of the corresponding TierProvider. function getProvider(uint256 blockId) external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; import "../common/EssentialContract.sol"; import "../common/LibStrings.sol"; /// @notice TaikoToken was `EssentialContract, ERC20SnapshotUpgradeable, ERC20VotesUpgradeable`. /// We use this contract to take 50 more slots to remove `ERC20SnapshotUpgradeable` from the parent /// contract list. /// We can simplify the code since we no longer need to maintain upgradability with Hekla. abstract contract TaikoTokenBase0 is EssentialContract { // solhint-disable var-name-mixedcase uint256[50] private __slots_previously_used_by_ERC20SnapshotUpgradeable; } /// @title TaikoTokenBase /// @notice The base contract for both the canonical and the bridged Taiko token. /// @custom:security-contact [email protected] abstract contract TaikoTokenBase is TaikoTokenBase0, ERC20VotesUpgradeable { uint256[50] private __gap; function clock() public view override returns (uint48) { return SafeCastUpgradeable.toUint48(block.timestamp); } // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public pure override returns (string memory) { // See https://eips.ethereum.org/EIPS/eip-6372 return "mode=timestamp"; } function symbol() public pure override returns (string memory) { return "TAIKO"; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC20Votes.sol) pragma solidity ^0.8.0; import "./ERC20PermitUpgradeable.sol"; import "../../../interfaces/IERC5805Upgradeable.sol"; import "../../../utils/math/MathUpgradeable.sol"; import "../../../utils/math/SafeCastUpgradeable.sol"; import "../../../utils/cryptography/ECDSAUpgradeable.sol"; import {Initializable} from "../../../proxy/utils/Initializable.sol"; /** * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. * * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. * * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting * power can be queried through the public accessors {getVotes} and {getPastVotes}. * * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. * * _Available since v4.2._ */ abstract contract ERC20VotesUpgradeable is Initializable, ERC20PermitUpgradeable, IERC5805Upgradeable { struct Checkpoint { uint32 fromBlock; uint224 votes; } bytes32 private constant _DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); mapping(address => address) private _delegates; mapping(address => Checkpoint[]) private _checkpoints; Checkpoint[] private _totalSupplyCheckpoints; function __ERC20Votes_init() internal onlyInitializing { } function __ERC20Votes_init_unchained() internal onlyInitializing { } /** * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). */ function clock() public view virtual override returns (uint48) { return SafeCastUpgradeable.toUint48(block.number); } /** * @dev Description of the clock */ // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() public view virtual override returns (string memory) { // Check that the clock was not modified require(clock() == block.number, "ERC20Votes: broken clock mode"); return "mode=blocknumber&from=default"; } /** * @dev Get the `pos`-th checkpoint for `account`. */ function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { return _checkpoints[account][pos]; } /** * @dev Get number of checkpoints for `account`. */ function numCheckpoints(address account) public view virtual returns (uint32) { return SafeCastUpgradeable.toUint32(_checkpoints[account].length); } /** * @dev Get the address `account` is currently delegating to. */ function delegates(address account) public view virtual override returns (address) { return _delegates[account]; } /** * @dev Gets the current votes balance for `account` */ function getVotes(address account) public view virtual override returns (uint256) { uint256 pos = _checkpoints[account].length; unchecked { return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; } } /** * @dev Retrieve the number of votes for `account` at the end of `timepoint`. * * Requirements: * * - `timepoint` must be in the past */ function getPastVotes(address account, uint256 timepoint) public view virtual override returns (uint256) { require(timepoint < clock(), "ERC20Votes: future lookup"); return _checkpointsLookup(_checkpoints[account], timepoint); } /** * @dev Retrieve the `totalSupply` at the end of `timepoint`. Note, this value is the sum of all balances. * It is NOT the sum of all the delegated votes! * * Requirements: * * - `timepoint` must be in the past */ function getPastTotalSupply(uint256 timepoint) public view virtual override returns (uint256) { require(timepoint < clock(), "ERC20Votes: future lookup"); return _checkpointsLookup(_totalSupplyCheckpoints, timepoint); } /** * @dev Lookup a value in a list of (sorted) checkpoints. */ function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 timepoint) private view returns (uint256) { // We run a binary search to look for the last (most recent) checkpoint taken before (or at) `timepoint`. // // Initially we check if the block is recent to narrow the search range. // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. // - If the middle checkpoint is after `timepoint`, we look in [low, mid) // - If the middle checkpoint is before or equal to `timepoint`, we look in [mid+1, high) // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not // out of bounds (in which case we're looking too far in the past and the result is 0). // Note that if the latest checkpoint available is exactly for `timepoint`, we end up with an index that is // past the end of the array, so we technically don't find a checkpoint after `timepoint`, but it works out // the same. uint256 length = ckpts.length; uint256 low = 0; uint256 high = length; if (length > 5) { uint256 mid = length - MathUpgradeable.sqrt(length); if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) { high = mid; } else { low = mid + 1; } } while (low < high) { uint256 mid = MathUpgradeable.average(low, high); if (_unsafeAccess(ckpts, mid).fromBlock > timepoint) { high = mid; } else { low = mid + 1; } } unchecked { return high == 0 ? 0 : _unsafeAccess(ckpts, high - 1).votes; } } /** * @dev Delegate votes from the sender to `delegatee`. */ function delegate(address delegatee) public virtual override { _delegate(_msgSender(), delegatee); } /** * @dev Delegates votes from signer to `delegatee` */ function delegateBySig( address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s ) public virtual override { require(block.timestamp <= expiry, "ERC20Votes: signature expired"); address signer = ECDSAUpgradeable.recover( _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), v, r, s ); require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); _delegate(signer, delegatee); } /** * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). */ function _maxSupply() internal view virtual returns (uint224) { return type(uint224).max; } /** * @dev Snapshots the totalSupply after it has been increased. */ function _mint(address account, uint256 amount) internal virtual override { super._mint(account, amount); require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); } /** * @dev Snapshots the totalSupply after it has been decreased. */ function _burn(address account, uint256 amount) internal virtual override { super._burn(account, amount); _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); } /** * @dev Move voting power when tokens are transferred. * * Emits a {IVotes-DelegateVotesChanged} event. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual override { super._afterTokenTransfer(from, to, amount); _moveVotingPower(delegates(from), delegates(to), amount); } /** * @dev Change delegation for `delegator` to `delegatee`. * * Emits events {IVotes-DelegateChanged} and {IVotes-DelegateVotesChanged}. */ function _delegate(address delegator, address delegatee) internal virtual { address currentDelegate = delegates(delegator); uint256 delegatorBalance = balanceOf(delegator); _delegates[delegator] = delegatee; emit DelegateChanged(delegator, currentDelegate, delegatee); _moveVotingPower(currentDelegate, delegatee, delegatorBalance); } function _moveVotingPower(address src, address dst, uint256 amount) private { if (src != dst && amount > 0) { if (src != address(0)) { (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); emit DelegateVotesChanged(src, oldWeight, newWeight); } if (dst != address(0)) { (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); emit DelegateVotesChanged(dst, oldWeight, newWeight); } } } function _writeCheckpoint( Checkpoint[] storage ckpts, function(uint256, uint256) view returns (uint256) op, uint256 delta ) private returns (uint256 oldWeight, uint256 newWeight) { uint256 pos = ckpts.length; unchecked { Checkpoint memory oldCkpt = pos == 0 ? Checkpoint(0, 0) : _unsafeAccess(ckpts, pos - 1); oldWeight = oldCkpt.votes; newWeight = op(oldWeight, delta); if (pos > 0 && oldCkpt.fromBlock == clock()) { _unsafeAccess(ckpts, pos - 1).votes = SafeCastUpgradeable.toUint224(newWeight); } else { ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(clock()), votes: SafeCastUpgradeable.toUint224(newWeight)})); } } } function _add(uint256 a, uint256 b) private pure returns (uint256) { return a + b; } function _subtract(uint256 a, uint256 b) private pure returns (uint256) { return a - b; } /** * @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds. */ function _unsafeAccess(Checkpoint[] storage ckpts, uint256 pos) private pure returns (Checkpoint storage result) { assembly { mstore(0, ckpts.slot) result.slot := add(keccak256(0, 0x20), pos) } } /** * @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[47] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/ERC20Permit.sol) pragma solidity ^0.8.0; import "./IERC20PermitUpgradeable.sol"; import "../ERC20Upgradeable.sol"; import "../../../utils/cryptography/ECDSAUpgradeable.sol"; import "../../../utils/cryptography/EIP712Upgradeable.sol"; import "../../../utils/CountersUpgradeable.sol"; import {Initializable} from "../../../proxy/utils/Initializable.sol"; /** * @dev Implementation 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. * * _Available since v3.4._ * * @custom:storage-size 51 */ abstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20PermitUpgradeable, EIP712Upgradeable { using CountersUpgradeable for CountersUpgradeable.Counter; mapping(address => CountersUpgradeable.Counter) private _nonces; // solhint-disable-next-line var-name-mixedcase bytes32 private constant _PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); /** * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. * However, to ensure consistency with the upgradeable transpiler, we will continue * to reserve a slot. * @custom:oz-renamed-from _PERMIT_TYPEHASH */ // solhint-disable-next-line var-name-mixedcase bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; /** * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. * * It's a good idea to use the same `name` that is defined as the ERC20 token name. */ function __ERC20Permit_init(string memory name) internal onlyInitializing { __EIP712_init_unchained(name, "1"); } function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {} /** * @inheritdoc IERC20PermitUpgradeable */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual override { require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); bytes32 hash = _hashTypedDataV4(structHash); address signer = ECDSAUpgradeable.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); _approve(owner, spender, value); } /** * @inheritdoc IERC20PermitUpgradeable */ function nonces(address owner) public view virtual override returns (uint256) { return _nonces[owner].current(); } /** * @inheritdoc IERC20PermitUpgradeable */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } /** * @dev "Consume a nonce": return the current value and increment. * * _Available since v4.1._ */ function _useNonce(address owner) internal virtual returns (uint256 current) { CountersUpgradeable.Counter storage nonce = _nonces[owner]; current = nonce.current(); nonce.increment(); } /** * @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) (interfaces/IERC5805.sol) pragma solidity ^0.8.0; import "../governance/utils/IVotesUpgradeable.sol"; import "./IERC6372Upgradeable.sol"; interface IERC5805Upgradeable is IERC6372Upgradeable, IVotesUpgradeable {}
// 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 MathUpgradeable { 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/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.0; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCastUpgradeable { /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toUint248(uint256 value) internal pure returns (uint248) { require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toUint240(uint256 value) internal pure returns (uint240) { require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toUint232(uint256 value) internal pure returns (uint232) { require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.2._ */ function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toUint216(uint256 value) internal pure returns (uint216) { require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toUint208(uint256 value) internal pure returns (uint208) { require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toUint200(uint256 value) internal pure returns (uint200) { require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toUint192(uint256 value) internal pure returns (uint192) { require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toUint184(uint256 value) internal pure returns (uint184) { require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toUint176(uint256 value) internal pure returns (uint176) { require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toUint168(uint256 value) internal pure returns (uint168) { require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toUint160(uint256 value) internal pure returns (uint160) { require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toUint152(uint256 value) internal pure returns (uint152) { require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toUint144(uint256 value) internal pure returns (uint144) { require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toUint136(uint256 value) internal pure returns (uint136) { require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v2.5._ */ function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toUint120(uint256 value) internal pure returns (uint120) { require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toUint112(uint256 value) internal pure returns (uint112) { require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toUint104(uint256 value) internal pure returns (uint104) { require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.2._ */ function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toUint88(uint256 value) internal pure returns (uint88) { require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toUint80(uint256 value) internal pure returns (uint80) { require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toUint72(uint256 value) internal pure returns (uint72) { require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v2.5._ */ function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toUint56(uint256 value) internal pure returns (uint56) { require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toUint48(uint256 value) internal pure returns (uint48) { require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toUint40(uint256 value) internal pure returns (uint40) { require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v2.5._ */ function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toUint24(uint256 value) internal pure returns (uint24) { require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v2.5._ */ function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v2.5._ */ function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. * * _Available since v3.0._ */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits * * _Available since v4.7._ */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); require(downcasted == value, "SafeCast: value doesn't fit in 248 bits"); } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits * * _Available since v4.7._ */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); require(downcasted == value, "SafeCast: value doesn't fit in 240 bits"); } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits * * _Available since v4.7._ */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); require(downcasted == value, "SafeCast: value doesn't fit in 232 bits"); } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits * * _Available since v4.7._ */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); require(downcasted == value, "SafeCast: value doesn't fit in 224 bits"); } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits * * _Available since v4.7._ */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); require(downcasted == value, "SafeCast: value doesn't fit in 216 bits"); } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits * * _Available since v4.7._ */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); require(downcasted == value, "SafeCast: value doesn't fit in 208 bits"); } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits * * _Available since v4.7._ */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); require(downcasted == value, "SafeCast: value doesn't fit in 200 bits"); } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits * * _Available since v4.7._ */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); require(downcasted == value, "SafeCast: value doesn't fit in 192 bits"); } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits * * _Available since v4.7._ */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); require(downcasted == value, "SafeCast: value doesn't fit in 184 bits"); } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits * * _Available since v4.7._ */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); require(downcasted == value, "SafeCast: value doesn't fit in 176 bits"); } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits * * _Available since v4.7._ */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); require(downcasted == value, "SafeCast: value doesn't fit in 168 bits"); } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits * * _Available since v4.7._ */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); require(downcasted == value, "SafeCast: value doesn't fit in 160 bits"); } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits * * _Available since v4.7._ */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); require(downcasted == value, "SafeCast: value doesn't fit in 152 bits"); } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits * * _Available since v4.7._ */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); require(downcasted == value, "SafeCast: value doesn't fit in 144 bits"); } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits * * _Available since v4.7._ */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); require(downcasted == value, "SafeCast: value doesn't fit in 136 bits"); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); require(downcasted == value, "SafeCast: value doesn't fit in 128 bits"); } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits * * _Available since v4.7._ */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); require(downcasted == value, "SafeCast: value doesn't fit in 120 bits"); } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits * * _Available since v4.7._ */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); require(downcasted == value, "SafeCast: value doesn't fit in 112 bits"); } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits * * _Available since v4.7._ */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); require(downcasted == value, "SafeCast: value doesn't fit in 104 bits"); } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits * * _Available since v4.7._ */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); require(downcasted == value, "SafeCast: value doesn't fit in 96 bits"); } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits * * _Available since v4.7._ */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); require(downcasted == value, "SafeCast: value doesn't fit in 88 bits"); } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits * * _Available since v4.7._ */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); require(downcasted == value, "SafeCast: value doesn't fit in 80 bits"); } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits * * _Available since v4.7._ */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); require(downcasted == value, "SafeCast: value doesn't fit in 72 bits"); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); require(downcasted == value, "SafeCast: value doesn't fit in 64 bits"); } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits * * _Available since v4.7._ */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); require(downcasted == value, "SafeCast: value doesn't fit in 56 bits"); } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits * * _Available since v4.7._ */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); require(downcasted == value, "SafeCast: value doesn't fit in 48 bits"); } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits * * _Available since v4.7._ */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); require(downcasted == value, "SafeCast: value doesn't fit in 40 bits"); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); require(downcasted == value, "SafeCast: value doesn't fit in 32 bits"); } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits * * _Available since v4.7._ */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); require(downcasted == value, "SafeCast: value doesn't fit in 24 bits"); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); require(downcasted == value, "SafeCast: value doesn't fit in 16 bits"); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); require(downcasted == value, "SafeCast: value doesn't fit in 8 bits"); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. * * _Available since v3.0._ */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../StringsUpgradeable.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 ECDSAUpgradeable { 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", StringsUpgradeable.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.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 IERC20PermitUpgradeable { /** * @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 // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20Upgradeable.sol"; import "./extensions/IERC20MetadataUpgradeable.sol"; import "../../utils/ContextUpgradeable.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing { __ERC20_init_unchained(name_, symbol_); } function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @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[45] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.8; import "./ECDSAUpgradeable.sol"; import "../../interfaces/IERC5267Upgradeable.sol"; import {Initializable} from "../../proxy/utils/Initializable.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain * separator of the implementation contract. This will cause the `_domainSeparatorV4` function to always rebuild the * separator from the immutable values, which is cheaper than accessing a cached version in cold storage. * * _Available since v3.4._ * * @custom:storage-size 52 */ abstract contract EIP712Upgradeable is Initializable, IERC5267Upgradeable { bytes32 private constant _TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /// @custom:oz-renamed-from _HASHED_NAME bytes32 private _hashedName; /// @custom:oz-renamed-from _HASHED_VERSION bytes32 private _hashedVersion; string private _name; string private _version; /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal onlyInitializing { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing { _name = name; _version = version; // Reset prior values in storage if upgrading _hashedName = 0; _hashedVersion = 0; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(); } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {EIP-5267}. * * _Available since v4.9._ */ function eip712Domain() public view virtual override returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized // and the EIP712 domain is not reliable, as it will be missing name and version. require(_hashedName == 0 && _hashedVersion == 0, "EIP712: Uninitialized"); return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Name() internal virtual view returns (string memory) { return _name; } /** * @dev The version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Version() internal virtual view returns (string memory) { return _version; } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead. */ function _EIP712NameHash() internal view returns (bytes32) { string memory name = _EIP712Name(); if (bytes(name).length > 0) { return keccak256(bytes(name)); } else { // If the name is empty, the contract may have been upgraded without initializing the new storage. // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design. bytes32 hashedName = _hashedName; if (hashedName != 0) { return hashedName; } else { return keccak256(""); } } } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead. */ function _EIP712VersionHash() internal view returns (bytes32) { string memory version = _EIP712Version(); if (bytes(version).length > 0) { return keccak256(bytes(version)); } else { // If the version is empty, the contract may have been upgraded without initializing the new storage. // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design. bytes32 hashedVersion = _hashedVersion; if (hashedVersion != 0) { return hashedVersion; } else { return keccak256(""); } } } /** * @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[48] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library CountersUpgradeable { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (governance/utils/IVotes.sol) pragma solidity ^0.8.0; /** * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts. * * _Available since v4.5._ */ interface IVotesUpgradeable { /** * @dev Emitted when an account changes their delegate. */ event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); /** * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes. */ event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); /** * @dev Returns the current amount of votes that `account` has. */ function getVotes(address account) external view returns (uint256); /** * @dev Returns the amount of votes that `account` had at a specific moment in the past. If the `clock()` is * configured to use block numbers, this will return the value at the end of the corresponding block. */ function getPastVotes(address account, uint256 timepoint) external view returns (uint256); /** * @dev Returns the total supply of votes available at a specific moment in the past. If the `clock()` is * configured to use block numbers, this will return the value at the end of the corresponding block. * * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. * Votes that have not been delegated are still part of total supply, even though they would not participate in a * vote. */ function getPastTotalSupply(uint256 timepoint) external view returns (uint256); /** * @dev Returns the delegate that `account` has chosen. */ function delegates(address account) external view returns (address); /** * @dev Delegates votes from the sender to `delegatee`. */ function delegate(address delegatee) external; /** * @dev Delegates votes from signer to `delegatee`. */ function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC6372.sol) pragma solidity ^0.8.0; interface IERC6372Upgradeable { /** * @dev Clock used for flagging checkpoints. Can be overridden to implement timestamp based checkpoints (and voting). */ function clock() external view returns (uint48); /** * @dev Description of the clock */ // solhint-disable-next-line func-name-mixedcase function CLOCK_MODE() external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/MathUpgradeable.sol"; import "./math/SignedMathUpgradeable.sol"; /** * @dev String operations. */ library StringsUpgradeable { 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 = MathUpgradeable.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(SignedMathUpgradeable.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, MathUpgradeable.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) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20Upgradeable { /** * @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 // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20Upgradeable.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20MetadataUpgradeable is IERC20Upgradeable { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC5267.sol) pragma solidity ^0.8.0; interface IERC5267Upgradeable { /** * @dev MAY be emitted to signal that the domain could have changed. */ event EIP712DomainChanged(); /** * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712 * signature. */ function eip712Domain() external view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ); }
// 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 SignedMathUpgradeable { /** * @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/", "forge-safe/=node_modules/forge-safe/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"ETH_TRANSFER_FAILED","type":"error"},{"inputs":[],"name":"FUNC_NOT_IMPLEMENTED","type":"error"},{"inputs":[],"name":"INVALID_PAUSE_STATUS","type":"error"},{"inputs":[],"name":"L1_ALREADY_CONTESTED","type":"error"},{"inputs":[],"name":"L1_ALREADY_CONTESTED","type":"error"},{"inputs":[],"name":"L1_ALREADY_PROVED","type":"error"},{"inputs":[],"name":"L1_ALREADY_PROVED","type":"error"},{"inputs":[],"name":"L1_BATCH_TRANSFER_FAILED","type":"error"},{"inputs":[],"name":"L1_BATCH_TRANSFER_FAILED","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_GENESIS_HASH","type":"error"},{"inputs":[],"name":"L1_INVALID_GENESIS_HASH","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_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_NOT_ASSIGNED_PROVER","type":"error"},{"inputs":[],"name":"L1_NOT_ASSIGNED_PROVER","type":"error"},{"inputs":[],"name":"L1_NO_HOOKS","type":"error"},{"inputs":[],"name":"L1_PROVING_PAUSED","type":"error"},{"inputs":[],"name":"L1_RECEIVE_DISABLED","type":"error"},{"inputs":[],"name":"L1_TOO_LATE","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_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_ADDRESS","type":"error"},{"inputs":[],"name":"ZERO_VALUE","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"indexed":true,"internalType":"address","name":"assignedProver","type":"address"},{"indexed":false,"internalType":"uint96","name":"livenessBond","type":"uint96"},{"components":[{"internalType":"bytes32","name":"l1Hash","type":"bytes32"},{"internalType":"bytes32","name":"difficulty","type":"bytes32"},{"internalType":"bytes32","name":"blobHash","type":"bytes32"},{"internalType":"bytes32","name":"extraData","type":"bytes32"},{"internalType":"bytes32","name":"depositsHash","type":"bytes32"},{"internalType":"address","name":"coinbase","type":"address"},{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"l1Height","type":"uint64"},{"internalType":"uint16","name":"minTier","type":"uint16"},{"internalType":"bool","name":"blobUsed","type":"bool"},{"internalType":"bytes32","name":"parentMetaHash","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"}],"indexed":false,"internalType":"struct TaikoData.BlockMetadata","name":"meta","type":"tuple"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint64","name":"id","type":"uint64"}],"indexed":false,"internalType":"struct TaikoData.EthDeposit[]","name":"depositsProcessed","type":"tuple[]"}],"name":"BlockProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"blockId","type":"uint256"},{"indexed":true,"internalType":"address","name":"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":[{"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":[{"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":"maxBlocksToVerify","type":"uint64"},{"internalType":"uint32","name":"blockMaxGasLimit","type":"uint32"},{"internalType":"uint96","name":"livenessBond","type":"uint96"},{"internalType":"uint8","name":"stateRootSyncInternal","type":"uint8"},{"internalType":"bool","name":"checkEOAForCalldataDA","type":"bool"}],"internalType":"struct TaikoData.Config","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getLastSyncedBlock","outputs":[{"internalType":"uint64","name":"blockId_","type":"uint64"},{"internalType":"bytes32","name":"blockHash_","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastVerifiedBlock","outputs":[{"internalType":"uint64","name":"blockId_","type":"uint64"},{"internalType":"bytes32","name":"blockHash_","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot_","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStateVariables","outputs":[{"components":[{"internalType":"uint64","name":"genesisHeight","type":"uint64"},{"internalType":"uint64","name":"genesisTimestamp","type":"uint64"},{"internalType":"uint64","name":"lastSyncedBlockId","type":"uint64"},{"internalType":"uint64","name":"lastSynecdAt","type":"uint64"}],"internalType":"struct TaikoData.SlotA","name":"","type":"tuple"},{"components":[{"internalType":"uint64","name":"numBlocks","type":"uint64"},{"internalType":"uint64","name":"lastVerifiedBlockId","type":"uint64"},{"internalType":"bool","name":"provingPaused","type":"bool"},{"internalType":"uint8","name":"__reservedB1","type":"uint8"},{"internalType":"uint16","name":"__reservedB2","type":"uint16"},{"internalType":"uint32","name":"__reservedB3","type":"uint32"},{"internalType":"uint64","name":"lastUnpausedAt","type":"uint64"}],"internalType":"struct TaikoData.SlotB","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"uint32","name":"_tid","type":"uint32"}],"name":"getTransition","outputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"address","name":"prover","type":"address"},{"internalType":"uint96","name":"validityBond","type":"uint96"},{"internalType":"address","name":"contester","type":"address"},{"internalType":"uint96","name":"contestBond","type":"uint96"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint16","name":"tier","type":"uint16"},{"internalType":"uint8","name":"__reserved1","type":"uint8"}],"internalType":"struct TaikoData.TransitionState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"bytes32","name":"_parentHash","type":"bytes32"}],"name":"getTransition","outputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"bytes32","name":"blockHash","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"address","name":"prover","type":"address"},{"internalType":"uint96","name":"validityBond","type":"uint96"},{"internalType":"address","name":"contester","type":"address"},{"internalType":"uint96","name":"contestBond","type":"uint96"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint16","name":"tier","type":"uint16"},{"internalType":"uint8","name":"__reserved1","type":"uint8"}],"internalType":"struct TaikoData.TransitionState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"impl","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inNonReentrant","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_addressManager","type":"address"},{"internalType":"bytes32","name":"_genesisBlockHash","type":"bytes32"},{"internalType":"bool","name":"_toPause","type":"bool"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"init2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastUnpausedAt","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_pause","type":"bool"}],"name":"pauseProving","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_params","type":"bytes"},{"internalType":"bytes","name":"_txList","type":"bytes"}],"name":"proposeBlock","outputs":[{"components":[{"internalType":"bytes32","name":"l1Hash","type":"bytes32"},{"internalType":"bytes32","name":"difficulty","type":"bytes32"},{"internalType":"bytes32","name":"blobHash","type":"bytes32"},{"internalType":"bytes32","name":"extraData","type":"bytes32"},{"internalType":"bytes32","name":"depositsHash","type":"bytes32"},{"internalType":"address","name":"coinbase","type":"address"},{"internalType":"uint64","name":"id","type":"uint64"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint64","name":"l1Height","type":"uint64"},{"internalType":"uint16","name":"minTier","type":"uint16"},{"internalType":"bool","name":"blobUsed","type":"bool"},{"internalType":"bytes32","name":"parentMetaHash","type":"bytes32"},{"internalType":"address","name":"sender","type":"address"}],"internalType":"struct TaikoData.BlockMetadata","name":"meta_","type":"tuple"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint96","name":"amount","type":"uint96"},{"internalType":"uint64","name":"id","type":"uint64"}],"internalType":"struct TaikoData.EthDeposit[]","name":"deposits_","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_blockId","type":"uint64"},{"internalType":"bytes","name":"_input","type":"bytes"}],"name":"proveBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_chainId","type":"uint64"},{"internalType":"bytes32","name":"_name","type":"bytes32"},{"internalType":"bool","name":"_allowZeroAddress","type":"bool"}],"name":"resolve","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_name","type":"bytes32"},{"internalType":"bool","name":"_allowZeroAddress","type":"bool"}],"name":"resolve","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"bytes32","name":"__reserve1","type":"bytes32"},{"components":[{"internalType":"uint64","name":"genesisHeight","type":"uint64"},{"internalType":"uint64","name":"genesisTimestamp","type":"uint64"},{"internalType":"uint64","name":"lastSyncedBlockId","type":"uint64"},{"internalType":"uint64","name":"lastSynecdAt","type":"uint64"}],"internalType":"struct TaikoData.SlotA","name":"slotA","type":"tuple"},{"components":[{"internalType":"uint64","name":"numBlocks","type":"uint64"},{"internalType":"uint64","name":"lastVerifiedBlockId","type":"uint64"},{"internalType":"bool","name":"provingPaused","type":"bool"},{"internalType":"uint8","name":"__reservedB1","type":"uint8"},{"internalType":"uint16","name":"__reservedB2","type":"uint16"},{"internalType":"uint32","name":"__reservedB3","type":"uint32"},{"internalType":"uint64","name":"lastUnpausedAt","type":"uint64"}],"internalType":"struct TaikoData.SlotB","name":"slotB","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_maxBlocksToVerify","type":"uint64"}],"name":"verifyBlocks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523060805234801562000014575f80fd5b506200001f6200002f565b620000296200002f565b620000ed565b5f54610100900460ff16156200009b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614620000eb575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b608051615db7620001225f395f8181610a1a01528181610a5a01528181610b2201528181610b620152610bdd0152615db75ff3fe6080604052600436106101d3575f3560e01c806379ba5097116100fd578063c3f909d411610092578063ef16e84511610062578063ef16e84514610629578063f2fde38b1461064a578063fd257e2914610669578063ff00c39114610688575f80fd5b8063c3f909d41461058c578063dde89cf5146105ad578063e07baba6146105cf578063e30c39781461060c575f80fd5b80638da5cb5b116100cd5780638da5cb5b1461045c5780639413caa914610479578063a86f9d9e1461048d578063c19d93fb146104ac575f80fd5b806379ba5097146104015780638456cb59146104155780638778209d146104295780638abf607714610448575f80fd5b80633eb6b8cf11610173578063563479a511610143578063563479a5146103755780635c975abb146103a15780635fa15e79146103c1578063715018a6146103ed575f80fd5b80633eb6b8cf1461030d5780633f4ba83a1461032c5780634f1ef2861461034057806352d1902d14610353575f80fd5b806329d1b62f116101ae57806329d1b62f146102745780633075db56146102935780633659cfe6146102b75780633ab76e9f146102d6575f80fd5b8063069489a21461020357806310d008bd1461021757806326af798614610236575f80fd5b366101ff576101e06106a7565b6101fd57604051630d28633960e01b815260040160405180910390fd5b005b5f80fd5b34801561020e575f80fd5b506101fd6106bb565b348015610222575f80fd5b506101fd610231366004614b45565b610772565b348015610241575f80fd5b5061024a6108fa565b604080516001600160401b0390941684526020840192909252908201526060015b60405180910390f35b34801561027f575f80fd5b506101fd61028e366004614bca565b61092d565b34801561029e575f80fd5b506102a76106a7565b604051901515815260200161026b565b3480156102c2575f80fd5b506101fd6102d1366004614c1a565b610a10565b3480156102e1575f80fd5b506097546102f5906001600160a01b031681565b6040516001600160a01b03909116815260200161026b565b348015610318575f80fd5b506102f5610327366004614c35565b610ad7565b348015610337575f80fd5b506101fd610aed565b6101fd61034e366004614d8e565b610b18565b34801561035e575f80fd5b50610367610bd1565b60405190815260200161026b565b348015610380575f80fd5b5061039461038f366004614ded565b610c82565b60405161026b9190614e1e565b3480156103ac575f80fd5b506102a760c954610100900460ff1660021490565b3480156103cc575f80fd5b506103e06103db366004614ee9565b610d46565b60405161026b9190614f02565b3480156103f8575f80fd5b506101fd610e2d565b34801561040c575f80fd5b506101fd610e40565b348015610420575f80fd5b506101fd610eb7565b348015610434575f80fd5b506101fd610443366004614ee9565b610eca565b348015610453575f80fd5b506102f5610fcd565b348015610467575f80fd5b506033546001600160a01b03166102f5565b348015610484575f80fd5b5061024a610fdb565b348015610498575f80fd5b506102f56104a7366004614f9a565b610ffd565b3480156104b7575f80fd5b5060fe54604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015261057d929183565b60405161026b9392919061502a565b348015610597575f80fd5b506105a0611009565b60405161026b919061507a565b3480156105b8575f80fd5b506105c16110a0565b60405161026b929190615108565b3480156105da575f80fd5b5060c9546105f4906201000090046001600160401b031681565b6040516001600160401b03909116815260200161026b565b348015610617575f80fd5b506065546001600160a01b03166102f5565b61063c610637366004615152565b61118a565b60405161026b929190615305565b348015610655575f80fd5b506101fd610664366004614c1a565b6112c6565b348015610674575f80fd5b5061039461068336600461532f565b611337565b348015610693575f80fd5b506101fd6106a2366004615357565b611353565b5f60026106b2611368565b60ff1614905090565b6106c36113a7565b5f54600290610100900460ff161580156106e357505f5460ff8083169116105b6107085760405162461bcd60e51b81526004016106ff90615372565b60405180910390fd5b5f8054610100805466ffffffffffffff60881b1916815560fe83905561ff001960ff851661ffff199093168317909117169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b61078660c954610100900460ff1660021490565b156107a45760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff16156107d0576040516333018e5560e11b815260040160405180910390fd5b60026107da611368565b60ff16036107fb5760405163dfc60d8560e01b815260040160405180910390fd5b6108056002611401565b5f808061081484860186615494565b9250925092508260c001516001600160401b0316866001600160401b03161461085057604051638a1c400f60e01b815260040160405180910390fd5b5f610859611009565b90505f6108746a3a30b4b5b7afba37b5b2b760a91b5f610ffd565b905061088660fb828430898989611449565b610895828660c001515f611f39565b156108ac576108ac60fb8284308660600151611fa8565b50506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b93506108e3925061010091506155c8565b60405180910390a16108f56001611401565b505050565b61010054600160401b90046001600160401b03165f8061092360fb61091d611009565b856129d2565b9394909392509050565b5f54610100900460ff161580801561094b57505f54600160ff909116105b806109645750303b15801561096457505f5460ff166001145b6109805760405162461bcd60e51b81526004016106ff90615372565b5f805460ff1916600117905580156109a1575f805461ff0019166101001790555b6109ab8585612a4b565b6109b660fb84612a85565b81156109c4576109c4612bd6565b8015610a09575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610a585760405162461bcd60e51b81526004016106ff90615630565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610a8a612c4d565b6001600160a01b031614610ab05760405162461bcd60e51b81526004016106ff9061567c565b610ab981612c68565b604080515f80825260208201909252610ad491839190612c70565b50565b5f610ae3848484612dda565b90505b9392505050565b610af5612ecb565b61010080546001600160c01b0316600160c01b426001600160401b031602179055565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610b605760405162461bcd60e51b81526004016106ff90615630565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610b92612c4d565b6001600160a01b031614610bb85760405162461bcd60e51b81526004016106ff9061567c565b610bc182612c68565b610bcd82826001612c70565b5050565b5f306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610c705760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106ff565b505f80516020615d3b83398151915290565b610c8a6148fd565b610c9e60fb610c97611009565b8585612edd565b6040805161014081018252825481526001830154602082015260028301549181019190915260038201546001600160a01b0380821660608401526001600160601b03600160a01b9283900481166080850152600485015491821660a08501529190041660c08201526005909101546001600160401b03811660e083015261ffff600160401b82041661010083015260ff600160501b9091041661012082015290505b92915050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152610d9960fb610d93611009565b84612f6b565b5060408051610100810182528254815260018301546001600160a01b03811660208301526001600160601b03600160a01b90910416918101919091526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b82041660a083015263ffffffff600160c01b8204811660c0840152600160e01b9091041660e082015292915050565b610e356113a7565b610e3e5f612fcb565b565b60655433906001600160a01b03168114610eae5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016106ff565b610ad481612fcb565b610ebf612bd6565b610e3e336001612fe4565b610ede60c954610100900460ff1660021490565b15610efc5760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610f28576040516333018e5560e11b815260040160405180910390fd5b6002610f32611368565b60ff1603610f535760405163dfc60d8560e01b815260040160405180910390fd5b610f5d6002611401565b610f8960fb610f7a6a3a30b4b5b7afba37b5b2b760a91b5f610ffd565b610f82611009565b3085611fa8565b6040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b90610fbb90610100906155c8565b60405180910390a1610ad46001611401565b5f610fd6612c4d565b905090565b60ff54600160801b90046001600160401b03165f8061092360fb61091d611009565b5f610ae6468484612dda565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915250604080516101008101825262028c5881526204f1a060208201526204f3a091810191909152601060608201819052630e4e1c0060808301526806c6b935b8bbd4000060a083015260c0820152600160e082015290565b604080516080810182525f8082526020820181905291810182905260608101919091526110cb614950565b5050604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015291565b61119261498b565b60606111a860c954610100900460ff1660021490565b156111c65760405163bae6e2a960e01b815260040160405180910390fd5b60026111d0611368565b60ff16036111f15760405163dfc60d8560e01b815260040160405180910390fd5b6111fb6002611401565b5f611204611009565b90505f61121f6a3a30b4b5b7afba37b5b2b760a91b5f610ffd565b905061123260fb8284308c8c8c8c613063565b60c082015191955093506112499083906001611f39565b8015611260575061010054600160801b900460ff16155b156112775761127760fb8284308660600151611fa8565b50506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b906112ab90610100906155c8565b60405180910390a16112bd6001611401565b94509492505050565b6112ce6113a7565b606580546001600160a01b0383166001600160a01b031990911681179091556112ff6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61133f6148fd565b610c9e60fb61134c611009565b85856138c0565b61135d3382612fe4565b610ad460fb8261393d565b5f611372466139ea565b1561139d57507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b6033546001600160a01b03163314610e3e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106ff565b61140a466139ea565b1561143557807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b8151158061145957506020820151155b8061146657506040820151155b15611484576040516317eddea160e11b815260040160405180910390fd5b61148c6149fe565b6001600160a01b0387166060808301919091526040805160e08101825260058b01546001600160401b038082168352600160401b820481166020840190815260ff600160801b84048116151595850195909552600160881b83049094169483019490945261ffff600160901b820416608083015263ffffffff600160a01b82041660a0830152600160c01b9004831660c0808301919091529084529051908601519082169116111580611552575080515160c08501516001600160401b03918216911610155b1561157057604051638a1c400f60e01b815260040160405180910390fd5b85604001518460c0015161158491906156dc565b6001600160401b0390811661010083018190525f90815260208a9052604090206002810154909116610120830181905260c08801516115c89160ff90911690613a17565b156115d857604084015160c08301525b60018101546001600160a01b031660a08301819052611606576101a08501516001600160a01b031660a08301525b6001810154600160a01b90046001600160601b031660e08301528054608083015260c08501516101208301516001600160401b039182169116141580611658575061165085613a44565b826080015114155b1561167657604051632ec3485560e11b815260040160405180910390fd5b61167e6148fd565b61168a8a838786613a73565b63ffffffff909116610140850152845190915061ffff1615806116bc575085610140015161ffff16845f015161ffff16105b806116d6575080610100015161ffff16845f015161ffff16105b156116f457604051631a32f51360e01b815260040160405180910390fd5b604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b0389169063a86f9d9e90604401602060405180830381865afa15801561174d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117719190615701565b610120850151604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa1580156117c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ec9190615701565b865160405163576c3de760e01b815261ffff90911660048201529091506001600160a01b0382169063576c3de79060240160c060405180830381865afa158015611838573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185c9190615732565b602086015261014088015160405163576c3de760e01b815261ffff90911660048201526001600160a01b0382169063576c3de79060240160c060405180830381865afa1580156118ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118d29190615732565b856040018190525050506119108160e001516001600160401b0316845f015160c001516001600160401b031685604001516080015161ffff16613c25565b156101a08401526020830151604001516001600160601b031615801590611942575060a08101516001600160a01b0316155b8015611959575082610140015163ffffffff166001145b801561196c575061010081015161ffff16155b801561197a5750826101a001515b156119b5578260a001516001600160a01b0316336001600160a01b0316146119b557604051632185a2ad60e21b815260040160405180910390fd5b60208301515115611b1f57602083015151604051635437cecf60e11b815260048101919091525f60248201819052906001600160a01b0389169063a86f9d9e90604401602060405180830381865afa158015611a13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a379190615701565b90505f82610100015161ffff16865f015161ffff16148015611a6957506020850151604001516001600160601b031615155b6040805160e08101825260808089015182528b8301516020830152338284018190526101208a01516001600160401b03166060840152841515918301919091526101608c0151151560a083015260c0820152905163043d132d60e31b8152919250906001600160a01b038416906321e8996890611aee9084908c908c9060040161582b565b5f604051808303815f87803b158015611b05575f80fd5b505af1158015611b17573d5f803e3d5ffd5b505050505050505b602080840151604001516001600160601b0316156101808501528181015190860151148015611b55575080604001518360c00151145b15156101c0840152610100810151845161ffff91821691161115611bdc57611b808282878787613c42565b8261012001516001600160401b03167fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f8633866020015160200151885f0151604051611bcf94939291906158c3565b60405180910390a2611e40565b826101c0015115611c0057604051639d49773160e01b815260040160405180910390fd5b82610180015115611cc15760208084015101516001600160601b031615611c2957611c29615916565b60808101516001600160601b0316158015611c4f575060a08101516001600160a01b0316155b611c5b57611c5b615916565b33606082018190526020808701519083015260c0840151604080840191909152610120850151865191516001600160401b03909116927fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f92611bcf928a92915f916158c3565b60a08101516001600160a01b031615611ced576040516382ef169960e01b815260040160405180910390fd5b611d228160e001516001600160401b0316845f015160c001516001600160401b031685602001516060015162ffffff16613c25565b15611d405760405163378b1eff60e21b815260040160405180910390fd5b602083015160409081015190516323b872dd60e01b81523360048201523060248201526001600160601b0390911660448201526001600160a01b038a16906323b872dd906064016020604051808303815f875af1158015611da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dc7919061592a565b506020830180516040908101516001600160601b031660c08401523360a084018190526101208601519251820151875192516001600160401b03909416937fb4c0a86c1ff239277697775b1e91d3375fd3a5ef6b345aa4e2f6001c890558f693611e37938b9390929091906158c3565b60405180910390a25b6001600160401b0342811660e083019081526101008086015183165f90815260029d8e01602090815260408083206101409099015163ffffffff1683529781529087902085518155908501516001820155958401519c86019c909c55606083015160808401516001600160601b03908116600160a01b9081026001600160a01b0393841617600389015560a086015160c087015190921602911617600486015551600590940180549b8301516101209093015160ff16600160501b0260ff60501b1961ffff909416600160401b0269ffffffffffffffffffff19909d1695909216949094179a909a171698909817905550505050505050565b5f83606001516001600160401b03165f03611f5557505f610ae6565b6060840151677fffffffffffffff600191821c16908111611f7a576001915050610ae6565b82611f8957600181901c611f8b565b5f5b611f9e826001600160401b038716615945565b1495945050505050565b6001600160401b03811615610a0957611fbf614ad9565b6040805160e08101825260058801546001600160401b038082168352600160401b82048116602080850191825260ff600160801b85048116151586880152600160881b850416606086015261ffff600160901b850416608086015263ffffffff600160a01b85041660a0860152600160c01b909304821660c0850152928552915190911690830181905290850151612056916156dc565b6001600160401b0390811660408084018290525f9182526020898152912090830151600282015491929182169116146120a257604051632ec3485560e11b815260040160405180910390fd5b6002810154600160e01b900463ffffffff1660a08301819052608083018190525f036120e15760405163d4345b9760e01b815260040160405180910390fd5b6040808301516001600160401b039081165f90815260028a016020908152838220608087015163ffffffff16835290529182206001015460e08501528481169081111561213057612130614c72565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b5090505f846001600160401b03166001600160401b0381111561217e5761217e614c72565b6040519080825280602002602001820160405280156121a7578160200160208202803683370190505b506020850180516001016001600160401b0316905290505b83515160208501516001600160401b0391821691161080156121f65750846001600160401b031684606001516001600160401b0316105b156126755786604001516001600160401b031684602001516001600160401b031681612224576122246156c8565b066001600160401b0390811660408681018290525f91825260208c81529120908601516002820154919550821691161461227157604051632ec3485560e11b815260040160405180910390fd5b612285898486604001518760e00151614073565b63ffffffff166080850181905215612675576040848101516001600160401b03165f90815260028b016020908152828220608088015163ffffffff1683529052206005810154600160401b900461ffff1660c086015260048101546001600160a01b0316156122f45750612675565b6101808501516001600160a01b031661239157604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201526001600160a01b0388169063a86f9d9e90604401602060405180830381865afa15801561235d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123819190615701565b6001600160a01b03166101808601525b6101808501516020860151604051635c42d07960e01b81526001600160401b0390911660048201525f916001600160a01b031690635c42d07990602401602060405180830381865afa1580156123e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061240d9190615701565b60c087015160405163576c3de760e01b815261ffff90911660048201526001600160a01b03919091169063576c3de79060240160c060405180830381865afa15801561245b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061247f9190615732565b606001516005830154875160c001519192506124ad916001600160401b03918216911662ffffff8416613c25565b6124b8575050612675565b50608085015163ffffffff1660a0860152600181015460e086015260038101546001600160a01b031661016086018190526060860151845185916001600160401b031690811061250a5761250a615958565b60200260200101906001600160a01b031690816001600160a01b0316815250508060030160149054906101000a90046001600160601b03166001600160601b03168286606001516001600160401b03168151811061256a5761256a615958565b6020026020010181815250508461016001516001600160a01b031685602001516001600160401b03167fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2898760e001515f8960c001516040516125e393929190928352602083019190915261ffff16604082015260600190565b60405180910390a36126098860c0015160ff1686602001516001600160401b0316613a17565b15612649576002810154801561264757610100860181905260208601516001600160401b0316610120870152608086015163ffffffff166101408701525b505b506020840180516001600160401b036001918201811690925260608601805190910190911690526121bf565b60608401516001600160401b0316156129c757606084015184516020015160408901519101906001600160401b03908116908216816126b6576126b66156c8565b066001600160401b03908116604087810182905260058d0180546fffffffffffffffff00000000000000001916600160401b8686160217905560a08801515f92835260208e90529181902060020180546001600160e01b0316600160e01b63ffffffff90941693909302929092179091556060870151909116808552808452905163446b4ad960e11b81526001600160a01b038b16906388d695b290612762908790879060040161596c565b6020604051808303815f875af115801561277e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a2919061592a565b6127bf576040516307600b4160e21b815260040160405180910390fd5b610100860151156129c45761012086015160048c0180546fffffffffffffffffffffffffffffffff16600160801b6001600160401b039384169081026001600160c01b031691909117600160c01b4285160217909155908316146128905788604001516001600160401b03168661012001516001600160401b031681612847576128476156c8565b066001600160401b031660408781018290526101408801515f92835260208e9052912060020180546001600160e01b0316600160e01b63ffffffff909316929092029190911790555b604051635437cecf60e11b81526d7369676e616c5f7365727669636560901b60048201525f60248201526001600160a01b0389169063a86f9d9e90604401602060405180830381865afa1580156128e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061290d9190615701565b89516101208801516101008901516040516313e4299d60e21b81526001600160401b0393841660048201527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da169602482015292909116604483015260648201526001600160a01b039190911690634f90a674906084016020604051808303815f875af115801561299e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129c291906159ee565b505b50505b505050505050505050565b5f805f806129e1878787612f6b565b60028201549193509150600160e01b900463ffffffff1615612a41576001600160401b0381165f90815260028881016020908152604080842086840154600160e01b900463ffffffff168552909152909120600181015491015490945092505b5050935093915050565b806001600160a01b038116612a735760405163538ba4f960e01b815260040160405180910390fd5b612a7c8361414c565b6108f5826141aa565b5f819003612aa65760405163d6d0f75560e01b815260040160405180910390fd5b600482018054426001600160401b03908116600160401b81026fffffffffffffffffffffffffffffffff1990931643929092169190911782179092556005808501805467ffffffffffffffff1990811660019081179092555f80805260208881526040808320600280820180546001600160e01b037fffffffff00000000ffffffffffffffff0000000000000000ffffffffffffffff909116909a17600160c11b1799909916600160e01b17909855858155968a01825280832085845282528083209485018990556003850180546001600160a01b031916905594840180549093169096179091558251868152948501819052918401829052919281907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a350505050565b612bea60c954610100900460ff1660021490565b15612c085760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b5f80516020615d3b833981519152546001600160a01b031690565b610ad46113a7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612ca3576108f58361421a565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612cfd575060408051601f3d908101601f19168201909252612cfa918101906159ee565b60015b612d605760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106ff565b5f80516020615d3b8339815191528114612dce5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106ff565b506108f58383836142b5565b6097545f906001600160a01b031680612e0657604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0386166004820152602481018590526001600160a01b038216906328f713cc90604401602060405180830381865afa158015612e58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e7c9190615701565b915082158015612e9357506001600160a01b038216155b15612ec357604051632b0d65db60e01b81526001600160401b0386166004820152602481018590526044016106ff565b509392505050565b612ed36142df565b610e3e335f612fe4565b5f805f612eeb878787612f6b565b915091508363ffffffff165f1480612f185750600282015463ffffffff600160c01b909104811690851610155b15612f365760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b03165f908152600287016020908152604080832063ffffffff8716845290915290209150505b949350505050565b5f80836040015183612f7d91906156dc565b6001600160401b038181165f9081526020889052604090206002810154909450919250848116911614612fc357604051638a1c400f60e01b815260040160405180910390fd5b935093915050565b606580546001600160a01b0319169055610ad481614369565b6d636861696e5f7761746368646f6760901b6130086033546001600160a01b031690565b6001600160a01b0316336001600160a01b031614158015613045575061302f816001610ffd565b6001600160a01b0316336001600160a01b031614155b156108f557604051630d85cccf60e11b815260040160405180910390fd5b61306b61498b565b60605f61307a86880188615ae1565b60208101519091506001600160a01b0316613096573360208201525b6040805160e08101825260058d01546001600160401b038082168352600160401b82048116602080850182905260ff600160801b85048116151596860196909652600160881b8404909516606085015261ffff600160901b840416608085015263ffffffff600160a01b84041660a0850152600160c01b9092041660c0830152918b015190916131269190615bb5565b613131906001615bb5565b6001600160401b0316815f01516001600160401b031610613165576040516351ec7d5360e01b815260040160405180910390fd5b5f8c5f015f8c604001516001855f015161317f9190615bd5565b61318991906156dc565b6001600160401b0316815260208101919091526040015f20546060840151909150158015906131bc575082606001518114155b156131da57604051630d41ec8760e11b815260040160405180910390fd5b604080516101c0810182525f194301804082525f60208084018290528385018290529387015160608401527f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd608080850191909152938701516001600160a01b031660a084015285516001600160401b0390811660c0850152938f015163ffffffff1660e08401524284166101008401529216610120820152610140810191909152861561016082018190526101808201839052336101a0830152909550156132f1576132a6466139ea565b6132c35760405163df9969ef60e01b815260040160405180910390fd5b5f80496040870181905290036132ec57604051639e7e2ddd60e01b815260040160405180910390fd5b613362565b8686604051613301929190615bf5565b60408051918290039091209086015260e08b015180156133445750336001600160a01b031661333886604001518560a001516143ba565b6001600160a01b031614155b156133625760405163f6ee3bdb60e01b815260040160405180910390fd5b81516040805144602082015260c09290921b6001600160c01b0319169082015243604882015260680160408051808303601f1901815291815281516020928301209187019190915251635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015613401573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134259190615701565b8351604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa158015613478573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061349c9190615701565b60208801516040516359ab4e2360e01b81529192506001600160a01b038316916359ab4e23916134d29160040190815260200190565b602060405180830381865afa1580156134ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135119190615c04565b61ffff1661014088015250506040805161010081019091525f908061353588613a44565b81526020015f6001600160a01b031681526020018d60a001516001600160601b03168152602001845f01516001600160401b031681526020018761010001516001600160401b03168152602001436001600160401b03168152602001600163ffffffff1681526020015f63ffffffff168152509050808e5f015f8e60400151865f01516135c291906156dc565b6001600160401b03166001600160401b031681526020019081526020015f205f820151815f01556020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160601b0302191690836001600160601b031602179055506060820151816002015f6101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160020160086101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160020160106101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160020160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600201601c6101000a81548163ffffffff021916908363ffffffff1602179055509050508d6005015f015f81819054906101000a90046001600160401b031660010191906101000a8154816001600160401b0302191690836001600160401b031602179055508c6001600160a01b03166323b872dd33308f60a001516040518463ffffffff1660e01b81526004016137b7939291906001600160a01b0393841681529190921660208201526001600160601b0391909116604082015260600190565b6020604051808303815f875af11580156137d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906137f7919061592a565b50341580159061380657504115155b156138155761381541346143d4565b604080515f8082526020820190925290613855565b604080516060810182525f80825260208083018290529282015282525f1990920191018161382a5790505b509450336001600160a01b03168660c001516001600160401b03167fcda4e564245eb15494bc6da29f6a42e1941cf57f5314bf35bab8a1fca0a9c60a8e60a0015189896040516138a793929190615c1f565b60405180910390a3505050509850989650505050505050565b5f805f6138ce878787612f6b565b915091505f6138df88848488614073565b90508063ffffffff165f036139075760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b039091165f908152600288016020908152604080832063ffffffff909416835292905220915050949350505050565b6005820154811515600160801b90910460ff161515036139705760405163689d009d60e11b815260040160405180910390fd5b60058201805460ff60801b1916600160801b83151502179055806139b1576005820180546001600160c01b0316600160c01b426001600160401b0316021790555b60405181151581527fed64db85835d07c3c990b8ebdd55e32d64e5ed53143b6ef2179e7bfaf17ddc3b9060200160405180910390a15050565b5f60018214806139fb575061426882145b80613a08575062aa36a782145b80610d405750610d40826143df565b5f60018311613a2857506001610d40565b60018303838381613a3b57613a3b6156c8565b06149392505050565b5f81604051602001613a569190615c4f565b604051602081830303815290604052805190602001209050919050565b5f613a7c6148fd565b613a908686856101000151875f0151614073565b91508163ffffffff165f03613b5157600285018054600163ffffffff600160c01b80840482168381019092160263ffffffff60c01b1990931692909217928390556001600160401b03600160401b9093049290921660e08401529250829003613b0f578351815260a08301516001600160a01b031660608201526112bd565b6101208301516001600160401b03165f9081526001870160209081526040808320875184529091529020805463ffffffff191663ffffffff84161790556112bd565b50610100808301516001600160401b039081165f90815260028089016020908152604080842063ffffffff8816855282529283902083516101408101855281548152600182015492810192909252918201549281019290925260038101546001600160a01b0380821660608501526001600160601b03600160a01b9283900481166080860152600484015491821660a08601529190041660c08301526005015491821660e082015261ffff600160401b8304169281019290925260ff600160501b9091041661012082015294509492505050565b5f80603c8302613c3586866143f6565b0142101595945050505050565b60a08401515f906001600160a01b031615613d9357816101c0015115613d0957613c788560c001516001600160601b031661440b565b60608084015190870151608088015160405163a9059cbb60e01b81526001600160a01b0392831660048201526001600160601b039091166024820152929350169063a9059cbb906044015b6020604051808303815f875af1158015613cdf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613d03919061592a565b50613ecf565b6002613d2186608001516001600160601b031661440b565b901c905081606001516001600160a01b031663a9059cbb8660a00151836003613d4a9190615c5e565b8860c001516001600160601b0316613d629190615c75565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401613cc3565b816101c0015115613db757604051639d49773160e01b815260040160405180910390fd5b613dcd85608001516001600160601b031661440b565b90508160e001516001600160601b03165f14613ecf576001860180546001600160a01b031690556020830151613e0490839061442d565b15613ecf57336001600160a01b03168260a001516001600160a01b031603613e455760e0820151613e3e906001600160601b031682615c75565b9050613ecf565b606082015160a083015160e084015160405163a9059cbb60e01b81526001600160a01b0392831660048201526001600160601b03909116602482015291169063a9059cbb906044016020604051808303815f875af1158015613ea9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613ecd919061592a565b505b8160200151602001516001600160601b0316811115613f75576060820151602080840151015160405163a9059cbb60e01b81523360048201526001600160601b03909116830360248201526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015613f4b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f6f919061592a565b5061401e565b8160200151602001516001600160601b031681101561401e57606082015160208084015101516040516323b872dd60e01b81523360048201523060248201526001600160601b0390911683900360448201526001600160a01b03909116906323b872dd906064016020604051808303815f875af1158015613ff8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061401c919061592a565b505b60208083015101516001600160601b031660808601525f60a0860152336060860152825161ffff166101008601526101c082015161406b576020808501519086015260c082015160408601525b505050505050565b6001600160401b0382165f9081526002850160209081526040808320600184529091528120548290036140da57506002830154600190600160c01b900463ffffffff1681106140d5576040516367a1907f60e01b815260040160405180910390fd5b612f63565b5060028301546001600160401b03165f908152600185016020908152604080832084845290915290205463ffffffff16801580159061412e5750600284015463ffffffff600160c01b909104811690821610155b15612f63576040516367a1907f60e01b815260040160405180910390fd5b5f54610100900460ff166141725760405162461bcd60e51b81526004016106ff90615c88565b61417a61449d565b6141986001600160a01b038216156141925781612fcb565b33612fcb565b5060c9805461ff001916610100179055565b5f54610100900460ff166141d05760405162461bcd60e51b81526004016106ff90615c88565b6001600160401b034611156141f85760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381163b6142875760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106ff565b5f80516020615d3b83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6142be836144c3565b5f825111806142ca5750805b156108f5576142d98383614502565b50505050565b6142f360c954610100900460ff1660021490565b6143105760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001612c43565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f805f6143c78585614527565b91509150612ec381614569565b610bcd82825a6146b2565b5f617e2c8210158015610d40575050617e90101590565b5f8183116144045781610ae6565b5090919050565b5f811561442657600361441f836007615c5e565b901c610d40565b5f92915050565b5f826101a00151801561444b575082610140015163ffffffff166001145b80610ae657508261018001518015614464575081516020145b8015610ae657507f20d34d7a20a139f9be221ba2163925c0c86ed02d34033f288f010d23a63ef4b761449583615cd3565b149392505050565b5f54610100900460ff16610e3e5760405162461bcd60e51b81526004016106ff90615c88565b6144cc8161421a565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610ae68383604051806060016040528060278152602001615d5b602791396146f5565b5f80825160410361455b576020830151604084015160608501515f1a61454f87828585614769565b94509450505050614562565b505f905060025b9250929050565b5f81600481111561457c5761457c615cf9565b036145845750565b600181600481111561459857614598615cf9565b036145e55760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016106ff565b60028160048111156145f9576145f9615cf9565b036146465760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106ff565b600381600481111561465a5761465a615cf9565b03610ad45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016106ff565b815f036146be57505050565b6146d883838360405180602001604052805f815250614823565b6108f557604051634c67134d60e11b815260040160405180910390fd5b60605f80856001600160a01b0316856040516147119190615d0d565b5f60405180830381855af49150503d805f8114614749576040519150601f19603f3d011682016040523d82523d5f602084013e61474e565b606091505b509150915061475f86838387614860565b9695505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561479e57505f905060036112bd565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156147ef573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116614817575f600192509250506112bd565b965f9650945050505050565b5f6001600160a01b03851661484b57604051634c67134d60e11b815260040160405180910390fd5b5f80835160208501878988f195945050505050565b606083156148ce5782515f036148c7576001600160a01b0385163b6148c75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106ff565b5081612f63565b612f6383838151156148e35781518083602001fd5b8060405162461bcd60e51b81526004016106ff9190615d28565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080516101c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b604051806101e00160405280614a12614950565b81526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a08201529101905b81525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082018190526101208201819052610140820181905261016082018190526101809091015290565b604051806101a00160405280614a7b614950565b80356001600160401b0381168114614b03575f80fd5b919050565b5f8083601f840112614b18575f80fd5b5081356001600160401b03811115614b2e575f80fd5b602083019150836020828501011115614562575f80fd5b5f805f60408486031215614b57575f80fd5b614b6084614aed565b925060208401356001600160401b03811115614b7a575f80fd5b614b8686828701614b08565b9497909650939450505050565b6001600160a01b0381168114610ad4575f80fd5b8035614b0381614b93565b8015158114610ad4575f80fd5b8035614b0381614bb2565b5f805f8060808587031215614bdd575f80fd5b8435614be881614b93565b93506020850135614bf881614b93565b9250604085013591506060850135614c0f81614bb2565b939692955090935050565b5f60208284031215614c2a575f80fd5b8135610ae681614b93565b5f805f60608486031215614c47575f80fd5b614c5084614aed565b9250602084013591506040840135614c6781614bb2565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715614ca857614ca8614c72565b60405290565b6040516101c081016001600160401b0381118282101715614ca857614ca8614c72565b60405160c081016001600160401b0381118282101715614ca857614ca8614c72565b604051601f8201601f191681016001600160401b0381118282101715614d1b57614d1b614c72565b604052919050565b5f82601f830112614d32575f80fd5b81356001600160401b03811115614d4b57614d4b614c72565b614d5e601f8201601f1916602001614cf3565b818152846020838601011115614d72575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614d9f575f80fd5b8235614daa81614b93565b915060208301356001600160401b03811115614dc4575f80fd5b614dd085828601614d23565b9150509250929050565b803563ffffffff81168114614b03575f80fd5b5f8060408385031215614dfe575f80fd5b614e0783614aed565b9150614e1560208401614dda565b90509250929050565b5f610140820190508251825260208301516020830152604083015160408301526060830151614e5860608401826001600160a01b03169052565b506080830151614e7360808401826001600160601b03169052565b5060a0830151614e8e60a08401826001600160a01b03169052565b5060c0830151614ea960c08401826001600160601b03169052565b5060e0830151614ec460e08401826001600160401b03169052565b506101008381015161ffff16908301526101209283015160ff16929091019190915290565b5f60208284031215614ef9575f80fd5b610ae682614aed565b815181526020808301516001600160a01b0316908201526040808301516001600160601b0316908201526060808301516001600160401b039081169183019190915260808084015182169083015260a080840151918216908301526101008201905060c0830151614f7b60c084018263ffffffff169052565b5060e0830151614f9360e084018263ffffffff169052565b5092915050565b5f8060408385031215614fab575f80fd5b823591506020830135614fbd81614bb2565b809150509250929050565b6001600160401b0380825116835280602083015116602084015260408201511515604084015260ff606083015116606084015261ffff608083015116608084015263ffffffff60a08301511660a08401528060c08301511660c0840152505050565b838152610180810161506d602083018580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b612f6360a0830184614fc8565b5f610100820190506001600160401b038084511683528060208501511660208401528060408501511660408401528060608501511660608401525063ffffffff608084015116608083015260a08301516150df60a08401826001600160601b03169052565b5060c08301516150f460c084018260ff169052565b5060e0830151614f9360e084018215159052565b6101608101615145828580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b610ae66080830184614fc8565b5f805f8060408587031215615165575f80fd5b84356001600160401b038082111561517b575f80fd5b61518788838901614b08565b9096509450602087013591508082111561519f575f80fd5b506151ac87828801614b08565b95989497509550505050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a08101516151fe60a08401826001600160a01b03169052565b5060c081015161521960c08401826001600160401b03169052565b5060e081015161523160e084018263ffffffff169052565b50610100818101516001600160401b039081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015115159083015261018080820151908301526101a0808201516001600160a01b038116828501526142d9565b5f815180845260208085019450602084015f5b838110156152fa57815180516001600160a01b03168852838101516001600160601b0316848901526040908101516001600160401b031690880152606090960195908201906001016152ad565b509495945050505050565b5f6101e061531383866151b8565b806101c08401526153268184018561529a565b95945050505050565b5f8060408385031215615340575f80fd5b61534983614aed565b946020939093013593505050565b5f60208284031215615367575f80fd5b8135610ae681614bb2565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b61ffff81168114610ad4575f80fd5b8035614b03816153c0565b5f608082840312156153ea575f80fd5b604051608081018181106001600160401b038211171561540c5761540c614c72565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b5f6040828403121561544d575f80fd5b615455614c86565b90508135615462816153c0565b815260208201356001600160401b0381111561547c575f80fd5b61548884828501614d23565b60208301525092915050565b5f805f8385036102608112156154a8575f80fd5b6101c0808212156154b7575f80fd5b6154bf614cae565b915085358252602086013560208301526040860135604083015260608601356060830152608086013560808301526154f960a08701614ba7565b60a083015261550a60c08701614aed565b60c083015261551b60e08701614dda565b60e083015261010061552e818801614aed565b90830152610120615540878201614aed565b908301526101406155528782016153cf565b90830152610160615564878201614bbf565b9083015261018086810135908301526101a0615581818801614ba7565b8184015250819450615595878288016153da565b935050506102408401356001600160401b038111156155b2575f80fd5b6155be8682870161543d565b9150509250925092565b5f60e08201905082546001600160401b038082168452808260401c1660208501525060ff8160801c161515604084015260ff8160881c16606084015261ffff8160901c16608084015263ffffffff8160a01c1660a08401528060c01c60c08401525092915050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b03808416806156f5576156f56156c8565b92169190910692915050565b5f60208284031215615711575f80fd5b8151610ae681614b93565b80516001600160601b0381168114614b03575f80fd5b5f60c08284031215615742575f80fd5b61574a614cd1565b8251815261575a6020840161571c565b602082015261576b6040840161571c565b6040820152606083015162ffffff81168114615785575f80fd5b60608201526080830151615798816153c0565b608082015260a083015160ff811681146157b0575f80fd5b60a08201529392505050565b5f5b838110156157d65781810151838201526020016157be565b50505f910152565b5f81518084526157f58160208601602086016157bc565b601f01601f19169290920160200192915050565b61ffff81511682525f602082015160406020850152612f6360408501826157de565b83518152602080850151818301526040808601516001600160a01b03908116828501526060808801516001600160401b03168186015260808089015115159086015260a08089015115159086015260c08089015190921691850191909152855160e0850152918501516101008401528401516101208301528301516101408201525f6101808061016084015261475f81840185615809565b845181526020808601519082015260408086015190820152606094850151948101949094526001600160a01b039290921660808401526001600160601b031660a083015261ffff1660c082015260e00190565b634e487b7160e01b5f52600160045260245ffd5b5f6020828403121561593a575f80fd5b8151610ae681614bb2565b5f82615953576159536156c8565b500690565b634e487b7160e01b5f52603260045260245ffd5b604080825283519082018190525f906020906060840190828701845b828110156159ad5781516001600160a01b031684529284019290840190600101615988565b505050838103828501528451808252858301918301905f5b818110156159e1578351835292840192918401916001016159c5565b5090979650505050505050565b5f602082840312156159fe575f80fd5b5051919050565b5f82601f830112615a14575f80fd5b813560206001600160401b0380831115615a3057615a30614c72565b8260051b615a3f838201614cf3565b9384528581018301938381019088861115615a58575f80fd5b84880192505b85831015615ad557823584811115615a74575f80fd5b88016040818b03601f1901811315615a8a575f80fd5b615a92614c86565b87830135615a9f81614b93565b8152908201359086821115615ab2575f80fd5b615ac08c8984860101614d23565b81890152845250509184019190840190615a5e565b98975050505050505050565b5f60208284031215615af1575f80fd5b81356001600160401b0380821115615b07575f80fd5b9083019060c08286031215615b1a575f80fd5b615b22614cd1565b615b2b83614ba7565b8152615b3960208401614ba7565b60208201526040830135604082015260608301356060820152608083013582811115615b63575f80fd5b615b6f87828601615a05565b60808301525060a083013582811115615b86575f80fd5b615b9287828601614d23565b60a08301525095945050505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115614f9357614f93615ba1565b6001600160401b03828116828216039080821115614f9357614f93615ba1565b818382375f9101908152919050565b5f60208284031215615c14575f80fd5b8151610ae6816153c0565b5f6102006001600160601b0386168352615c3c60208401866151b8565b806101e084015261475f8184018561529a565b6101c08101610d4082846151b8565b8082028115828204841417610d4057610d40615ba1565b80820180821115610d4057610d40615ba1565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b80516020808301519190811015615cf3575f198160200360031b1b821691505b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f8251615d1e8184602087016157bc565b9190910192915050565b602081525f610ae660208301846157de56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220326b0dffa124ebf142f195b9a1744708d52ed7369b839aedb262467ed79e2b9464736f6c63430008180033
Deployed Bytecode
0x6080604052600436106101d3575f3560e01c806379ba5097116100fd578063c3f909d411610092578063ef16e84511610062578063ef16e84514610629578063f2fde38b1461064a578063fd257e2914610669578063ff00c39114610688575f80fd5b8063c3f909d41461058c578063dde89cf5146105ad578063e07baba6146105cf578063e30c39781461060c575f80fd5b80638da5cb5b116100cd5780638da5cb5b1461045c5780639413caa914610479578063a86f9d9e1461048d578063c19d93fb146104ac575f80fd5b806379ba5097146104015780638456cb59146104155780638778209d146104295780638abf607714610448575f80fd5b80633eb6b8cf11610173578063563479a511610143578063563479a5146103755780635c975abb146103a15780635fa15e79146103c1578063715018a6146103ed575f80fd5b80633eb6b8cf1461030d5780633f4ba83a1461032c5780634f1ef2861461034057806352d1902d14610353575f80fd5b806329d1b62f116101ae57806329d1b62f146102745780633075db56146102935780633659cfe6146102b75780633ab76e9f146102d6575f80fd5b8063069489a21461020357806310d008bd1461021757806326af798614610236575f80fd5b366101ff576101e06106a7565b6101fd57604051630d28633960e01b815260040160405180910390fd5b005b5f80fd5b34801561020e575f80fd5b506101fd6106bb565b348015610222575f80fd5b506101fd610231366004614b45565b610772565b348015610241575f80fd5b5061024a6108fa565b604080516001600160401b0390941684526020840192909252908201526060015b60405180910390f35b34801561027f575f80fd5b506101fd61028e366004614bca565b61092d565b34801561029e575f80fd5b506102a76106a7565b604051901515815260200161026b565b3480156102c2575f80fd5b506101fd6102d1366004614c1a565b610a10565b3480156102e1575f80fd5b506097546102f5906001600160a01b031681565b6040516001600160a01b03909116815260200161026b565b348015610318575f80fd5b506102f5610327366004614c35565b610ad7565b348015610337575f80fd5b506101fd610aed565b6101fd61034e366004614d8e565b610b18565b34801561035e575f80fd5b50610367610bd1565b60405190815260200161026b565b348015610380575f80fd5b5061039461038f366004614ded565b610c82565b60405161026b9190614e1e565b3480156103ac575f80fd5b506102a760c954610100900460ff1660021490565b3480156103cc575f80fd5b506103e06103db366004614ee9565b610d46565b60405161026b9190614f02565b3480156103f8575f80fd5b506101fd610e2d565b34801561040c575f80fd5b506101fd610e40565b348015610420575f80fd5b506101fd610eb7565b348015610434575f80fd5b506101fd610443366004614ee9565b610eca565b348015610453575f80fd5b506102f5610fcd565b348015610467575f80fd5b506033546001600160a01b03166102f5565b348015610484575f80fd5b5061024a610fdb565b348015610498575f80fd5b506102f56104a7366004614f9a565b610ffd565b3480156104b7575f80fd5b5060fe54604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015261057d929183565b60405161026b9392919061502a565b348015610597575f80fd5b506105a0611009565b60405161026b919061507a565b3480156105b8575f80fd5b506105c16110a0565b60405161026b929190615108565b3480156105da575f80fd5b5060c9546105f4906201000090046001600160401b031681565b6040516001600160401b03909116815260200161026b565b348015610617575f80fd5b506065546001600160a01b03166102f5565b61063c610637366004615152565b61118a565b60405161026b929190615305565b348015610655575f80fd5b506101fd610664366004614c1a565b6112c6565b348015610674575f80fd5b5061039461068336600461532f565b611337565b348015610693575f80fd5b506101fd6106a2366004615357565b611353565b5f60026106b2611368565b60ff1614905090565b6106c36113a7565b5f54600290610100900460ff161580156106e357505f5460ff8083169116105b6107085760405162461bcd60e51b81526004016106ff90615372565b60405180910390fd5b5f8054610100805466ffffffffffffff60881b1916815560fe83905561ff001960ff851661ffff199093168317909117169091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b61078660c954610100900460ff1660021490565b156107a45760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff16156107d0576040516333018e5560e11b815260040160405180910390fd5b60026107da611368565b60ff16036107fb5760405163dfc60d8560e01b815260040160405180910390fd5b6108056002611401565b5f808061081484860186615494565b9250925092508260c001516001600160401b0316866001600160401b03161461085057604051638a1c400f60e01b815260040160405180910390fd5b5f610859611009565b90505f6108746a3a30b4b5b7afba37b5b2b760a91b5f610ffd565b905061088660fb828430898989611449565b610895828660c001515f611f39565b156108ac576108ac60fb8284308660600151611fa8565b50506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b93506108e3925061010091506155c8565b60405180910390a16108f56001611401565b505050565b61010054600160401b90046001600160401b03165f8061092360fb61091d611009565b856129d2565b9394909392509050565b5f54610100900460ff161580801561094b57505f54600160ff909116105b806109645750303b15801561096457505f5460ff166001145b6109805760405162461bcd60e51b81526004016106ff90615372565b5f805460ff1916600117905580156109a1575f805461ff0019166101001790555b6109ab8585612a4b565b6109b660fb84612a85565b81156109c4576109c4612bd6565b8015610a09575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b037f0000000000000000000000005fc54737ecc1de49d58ae1195d4a296257f1e31b163003610a585760405162461bcd60e51b81526004016106ff90615630565b7f0000000000000000000000005fc54737ecc1de49d58ae1195d4a296257f1e31b6001600160a01b0316610a8a612c4d565b6001600160a01b031614610ab05760405162461bcd60e51b81526004016106ff9061567c565b610ab981612c68565b604080515f80825260208201909252610ad491839190612c70565b50565b5f610ae3848484612dda565b90505b9392505050565b610af5612ecb565b61010080546001600160c01b0316600160c01b426001600160401b031602179055565b6001600160a01b037f0000000000000000000000005fc54737ecc1de49d58ae1195d4a296257f1e31b163003610b605760405162461bcd60e51b81526004016106ff90615630565b7f0000000000000000000000005fc54737ecc1de49d58ae1195d4a296257f1e31b6001600160a01b0316610b92612c4d565b6001600160a01b031614610bb85760405162461bcd60e51b81526004016106ff9061567c565b610bc182612c68565b610bcd82826001612c70565b5050565b5f306001600160a01b037f0000000000000000000000005fc54737ecc1de49d58ae1195d4a296257f1e31b1614610c705760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016106ff565b505f80516020615d3b83398151915290565b610c8a6148fd565b610c9e60fb610c97611009565b8585612edd565b6040805161014081018252825481526001830154602082015260028301549181019190915260038201546001600160a01b0380821660608401526001600160601b03600160a01b9283900481166080850152600485015491821660a08501529190041660c08201526005909101546001600160401b03811660e083015261ffff600160401b82041661010083015260ff600160501b9091041661012082015290505b92915050565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810191909152610d9960fb610d93611009565b84612f6b565b5060408051610100810182528254815260018301546001600160a01b03811660208301526001600160601b03600160a01b90910416918101919091526002909101546001600160401b038082166060840152600160401b820481166080840152600160801b82041660a083015263ffffffff600160c01b8204811660c0840152600160e01b9091041660e082015292915050565b610e356113a7565b610e3e5f612fcb565b565b60655433906001600160a01b03168114610eae5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016106ff565b610ad481612fcb565b610ebf612bd6565b610e3e336001612fe4565b610ede60c954610100900460ff1660021490565b15610efc5760405163bae6e2a960e01b815260040160405180910390fd5b61010054600160801b900460ff1615610f28576040516333018e5560e11b815260040160405180910390fd5b6002610f32611368565b60ff1603610f535760405163dfc60d8560e01b815260040160405180910390fd5b610f5d6002611401565b610f8960fb610f7a6a3a30b4b5b7afba37b5b2b760a91b5f610ffd565b610f82611009565b3085611fa8565b6040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b90610fbb90610100906155c8565b60405180910390a1610ad46001611401565b5f610fd6612c4d565b905090565b60ff54600160801b90046001600160401b03165f8061092360fb61091d611009565b5f610ae6468484612dda565b60408051610100810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915250604080516101008101825262028c5881526204f1a060208201526204f3a091810191909152601060608201819052630e4e1c0060808301526806c6b935b8bbd4000060a083015260c0820152600160e082015290565b604080516080810182525f8082526020820181905291810182905260608101919091526110cb614950565b5050604080516080808201835260ff80546001600160401b038082168552600160401b8083048216602080880191909152600160801b8085048416888a0152600160c01b9485900484166060808a0191909152895160e081018b526101005480871682529485048616938101939093529083048616151598820198909852600160881b82049094169684019690965261ffff600160901b8704169383019390935263ffffffff600160a01b86041660a08301529093041660c083015291565b61119261498b565b60606111a860c954610100900460ff1660021490565b156111c65760405163bae6e2a960e01b815260040160405180910390fd5b60026111d0611368565b60ff16036111f15760405163dfc60d8560e01b815260040160405180910390fd5b6111fb6002611401565b5f611204611009565b90505f61121f6a3a30b4b5b7afba37b5b2b760a91b5f610ffd565b905061123260fb8284308c8c8c8c613063565b60c082015191955093506112499083906001611f39565b8015611260575061010054600160801b900460ff16155b156112775761127760fb8284308660600151611fa8565b50506040517fdf66aee38ea9fe523cfd238705d455a354305a646748dbb931898b51cee4727b906112ab90610100906155c8565b60405180910390a16112bd6001611401565b94509492505050565b6112ce6113a7565b606580546001600160a01b0383166001600160a01b031990911681179091556112ff6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61133f6148fd565b610c9e60fb61134c611009565b85856138c0565b61135d3382612fe4565b610ad460fb8261393d565b5f611372466139ea565b1561139d57507fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5c90565b5060c95460ff1690565b6033546001600160a01b03163314610e3e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106ff565b61140a466139ea565b1561143557807fa5054f728453d3dbe953bdc43e4d0cb97e662ea32d7958190f3dc2da31d9721b5d50565b60c9805460ff831660ff1990911617905550565b8151158061145957506020820151155b8061146657506040820151155b15611484576040516317eddea160e11b815260040160405180910390fd5b61148c6149fe565b6001600160a01b0387166060808301919091526040805160e08101825260058b01546001600160401b038082168352600160401b820481166020840190815260ff600160801b84048116151595850195909552600160881b83049094169483019490945261ffff600160901b820416608083015263ffffffff600160a01b82041660a0830152600160c01b9004831660c0808301919091529084529051908601519082169116111580611552575080515160c08501516001600160401b03918216911610155b1561157057604051638a1c400f60e01b815260040160405180910390fd5b85604001518460c0015161158491906156dc565b6001600160401b0390811661010083018190525f90815260208a9052604090206002810154909116610120830181905260c08801516115c89160ff90911690613a17565b156115d857604084015160c08301525b60018101546001600160a01b031660a08301819052611606576101a08501516001600160a01b031660a08301525b6001810154600160a01b90046001600160601b031660e08301528054608083015260c08501516101208301516001600160401b039182169116141580611658575061165085613a44565b826080015114155b1561167657604051632ec3485560e11b815260040160405180910390fd5b61167e6148fd565b61168a8a838786613a73565b63ffffffff909116610140850152845190915061ffff1615806116bc575085610140015161ffff16845f015161ffff16105b806116d6575080610100015161ffff16845f015161ffff16105b156116f457604051631a32f51360e01b815260040160405180910390fd5b604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b0389169063a86f9d9e90604401602060405180830381865afa15801561174d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117719190615701565b610120850151604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa1580156117c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117ec9190615701565b865160405163576c3de760e01b815261ffff90911660048201529091506001600160a01b0382169063576c3de79060240160c060405180830381865afa158015611838573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061185c9190615732565b602086015261014088015160405163576c3de760e01b815261ffff90911660048201526001600160a01b0382169063576c3de79060240160c060405180830381865afa1580156118ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118d29190615732565b856040018190525050506119108160e001516001600160401b0316845f015160c001516001600160401b031685604001516080015161ffff16613c25565b156101a08401526020830151604001516001600160601b031615801590611942575060a08101516001600160a01b0316155b8015611959575082610140015163ffffffff166001145b801561196c575061010081015161ffff16155b801561197a5750826101a001515b156119b5578260a001516001600160a01b0316336001600160a01b0316146119b557604051632185a2ad60e21b815260040160405180910390fd5b60208301515115611b1f57602083015151604051635437cecf60e11b815260048101919091525f60248201819052906001600160a01b0389169063a86f9d9e90604401602060405180830381865afa158015611a13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a379190615701565b90505f82610100015161ffff16865f015161ffff16148015611a6957506020850151604001516001600160601b031615155b6040805160e08101825260808089015182528b8301516020830152338284018190526101208a01516001600160401b03166060840152841515918301919091526101608c0151151560a083015260c0820152905163043d132d60e31b8152919250906001600160a01b038416906321e8996890611aee9084908c908c9060040161582b565b5f604051808303815f87803b158015611b05575f80fd5b505af1158015611b17573d5f803e3d5ffd5b505050505050505b602080840151604001516001600160601b0316156101808501528181015190860151148015611b55575080604001518360c00151145b15156101c0840152610100810151845161ffff91821691161115611bdc57611b808282878787613c42565b8261012001516001600160401b03167fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f8633866020015160200151885f0151604051611bcf94939291906158c3565b60405180910390a2611e40565b826101c0015115611c0057604051639d49773160e01b815260040160405180910390fd5b82610180015115611cc15760208084015101516001600160601b031615611c2957611c29615916565b60808101516001600160601b0316158015611c4f575060a08101516001600160a01b0316155b611c5b57611c5b615916565b33606082018190526020808701519083015260c0840151604080840191909152610120850151865191516001600160401b03909116927fc195e4be3b936845492b8be4b1cf604db687a4d79ad84d979499c136f8e6701f92611bcf928a92915f916158c3565b60a08101516001600160a01b031615611ced576040516382ef169960e01b815260040160405180910390fd5b611d228160e001516001600160401b0316845f015160c001516001600160401b031685602001516060015162ffffff16613c25565b15611d405760405163378b1eff60e21b815260040160405180910390fd5b602083015160409081015190516323b872dd60e01b81523360048201523060248201526001600160601b0390911660448201526001600160a01b038a16906323b872dd906064016020604051808303815f875af1158015611da3573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dc7919061592a565b506020830180516040908101516001600160601b031660c08401523360a084018190526101208601519251820151875192516001600160401b03909416937fb4c0a86c1ff239277697775b1e91d3375fd3a5ef6b345aa4e2f6001c890558f693611e37938b9390929091906158c3565b60405180910390a25b6001600160401b0342811660e083019081526101008086015183165f90815260029d8e01602090815260408083206101409099015163ffffffff1683529781529087902085518155908501516001820155958401519c86019c909c55606083015160808401516001600160601b03908116600160a01b9081026001600160a01b0393841617600389015560a086015160c087015190921602911617600486015551600590940180549b8301516101209093015160ff16600160501b0260ff60501b1961ffff909416600160401b0269ffffffffffffffffffff19909d1695909216949094179a909a171698909817905550505050505050565b5f83606001516001600160401b03165f03611f5557505f610ae6565b6060840151677fffffffffffffff600191821c16908111611f7a576001915050610ae6565b82611f8957600181901c611f8b565b5f5b611f9e826001600160401b038716615945565b1495945050505050565b6001600160401b03811615610a0957611fbf614ad9565b6040805160e08101825260058801546001600160401b038082168352600160401b82048116602080850191825260ff600160801b85048116151586880152600160881b850416606086015261ffff600160901b850416608086015263ffffffff600160a01b85041660a0860152600160c01b909304821660c0850152928552915190911690830181905290850151612056916156dc565b6001600160401b0390811660408084018290525f9182526020898152912090830151600282015491929182169116146120a257604051632ec3485560e11b815260040160405180910390fd5b6002810154600160e01b900463ffffffff1660a08301819052608083018190525f036120e15760405163d4345b9760e01b815260040160405180910390fd5b6040808301516001600160401b039081165f90815260028a016020908152838220608087015163ffffffff16835290529182206001015460e08501528481169081111561213057612130614c72565b604051908082528060200260200182016040528015612159578160200160208202803683370190505b5090505f846001600160401b03166001600160401b0381111561217e5761217e614c72565b6040519080825280602002602001820160405280156121a7578160200160208202803683370190505b506020850180516001016001600160401b0316905290505b83515160208501516001600160401b0391821691161080156121f65750846001600160401b031684606001516001600160401b0316105b156126755786604001516001600160401b031684602001516001600160401b031681612224576122246156c8565b066001600160401b0390811660408681018290525f91825260208c81529120908601516002820154919550821691161461227157604051632ec3485560e11b815260040160405180910390fd5b612285898486604001518760e00151614073565b63ffffffff166080850181905215612675576040848101516001600160401b03165f90815260028b016020908152828220608088015163ffffffff1683529052206005810154600160401b900461ffff1660c086015260048101546001600160a01b0316156122f45750612675565b6101808501516001600160a01b031661239157604051635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201526001600160a01b0388169063a86f9d9e90604401602060405180830381865afa15801561235d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123819190615701565b6001600160a01b03166101808601525b6101808501516020860151604051635c42d07960e01b81526001600160401b0390911660048201525f916001600160a01b031690635c42d07990602401602060405180830381865afa1580156123e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061240d9190615701565b60c087015160405163576c3de760e01b815261ffff90911660048201526001600160a01b03919091169063576c3de79060240160c060405180830381865afa15801561245b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061247f9190615732565b606001516005830154875160c001519192506124ad916001600160401b03918216911662ffffff8416613c25565b6124b8575050612675565b50608085015163ffffffff1660a0860152600181015460e086015260038101546001600160a01b031661016086018190526060860151845185916001600160401b031690811061250a5761250a615958565b60200260200101906001600160a01b031690816001600160a01b0316815250508060030160149054906101000a90046001600160601b03166001600160601b03168286606001516001600160401b03168151811061256a5761256a615958565b6020026020010181815250508461016001516001600160a01b031685602001516001600160401b03167fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2898760e001515f8960c001516040516125e393929190928352602083019190915261ffff16604082015260600190565b60405180910390a36126098860c0015160ff1686602001516001600160401b0316613a17565b15612649576002810154801561264757610100860181905260208601516001600160401b0316610120870152608086015163ffffffff166101408701525b505b506020840180516001600160401b036001918201811690925260608601805190910190911690526121bf565b60608401516001600160401b0316156129c757606084015184516020015160408901519101906001600160401b03908116908216816126b6576126b66156c8565b066001600160401b03908116604087810182905260058d0180546fffffffffffffffff00000000000000001916600160401b8686160217905560a08801515f92835260208e90529181902060020180546001600160e01b0316600160e01b63ffffffff90941693909302929092179091556060870151909116808552808452905163446b4ad960e11b81526001600160a01b038b16906388d695b290612762908790879060040161596c565b6020604051808303815f875af115801561277e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a2919061592a565b6127bf576040516307600b4160e21b815260040160405180910390fd5b610100860151156129c45761012086015160048c0180546fffffffffffffffffffffffffffffffff16600160801b6001600160401b039384169081026001600160c01b031691909117600160c01b4285160217909155908316146128905788604001516001600160401b03168661012001516001600160401b031681612847576128476156c8565b066001600160401b031660408781018290526101408801515f92835260208e9052912060020180546001600160e01b0316600160e01b63ffffffff909316929092029190911790555b604051635437cecf60e11b81526d7369676e616c5f7365727669636560901b60048201525f60248201526001600160a01b0389169063a86f9d9e90604401602060405180830381865afa1580156128e9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061290d9190615701565b89516101208801516101008901516040516313e4299d60e21b81526001600160401b0393841660048201527f73e6d340850343cc6f001515dc593377337c95a6ffe034fe1e844d4dab5da169602482015292909116604483015260648201526001600160a01b039190911690634f90a674906084016020604051808303815f875af115801561299e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129c291906159ee565b505b50505b505050505050505050565b5f805f806129e1878787612f6b565b60028201549193509150600160e01b900463ffffffff1615612a41576001600160401b0381165f90815260028881016020908152604080842086840154600160e01b900463ffffffff168552909152909120600181015491015490945092505b5050935093915050565b806001600160a01b038116612a735760405163538ba4f960e01b815260040160405180910390fd5b612a7c8361414c565b6108f5826141aa565b5f819003612aa65760405163d6d0f75560e01b815260040160405180910390fd5b600482018054426001600160401b03908116600160401b81026fffffffffffffffffffffffffffffffff1990931643929092169190911782179092556005808501805467ffffffffffffffff1990811660019081179092555f80805260208881526040808320600280820180546001600160e01b037fffffffff00000000ffffffffffffffff0000000000000000ffffffffffffffff909116909a17600160c11b1799909916600160e01b17909855858155968a01825280832085845282528083209485018990556003850180546001600160a01b031916905594840180549093169096179091558251868152948501819052918401829052919281907fdecbd2c61cbda254917d6fd4c980a470701e8f9f1b744f6ad163ca70ca5db2899060600160405180910390a350505050565b612bea60c954610100900460ff1660021490565b15612c085760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461ff0019166102001790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020015b60405180910390a1565b5f80516020615d3b833981519152546001600160a01b031690565b610ad46113a7565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615612ca3576108f58361421a565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612cfd575060408051601f3d908101601f19168201909252612cfa918101906159ee565b60015b612d605760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b60648201526084016106ff565b5f80516020615d3b8339815191528114612dce5760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b60648201526084016106ff565b506108f58383836142b5565b6097545f906001600160a01b031680612e0657604051638ed88b2560e01b815260040160405180910390fd5b604051630a3dc4f360e21b81526001600160401b0386166004820152602481018590526001600160a01b038216906328f713cc90604401602060405180830381865afa158015612e58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e7c9190615701565b915082158015612e9357506001600160a01b038216155b15612ec357604051632b0d65db60e01b81526001600160401b0386166004820152602481018590526044016106ff565b509392505050565b612ed36142df565b610e3e335f612fe4565b5f805f612eeb878787612f6b565b915091508363ffffffff165f1480612f185750600282015463ffffffff600160c01b909104811690851610155b15612f365760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b03165f908152600287016020908152604080832063ffffffff8716845290915290209150505b949350505050565b5f80836040015183612f7d91906156dc565b6001600160401b038181165f9081526020889052604090206002810154909450919250848116911614612fc357604051638a1c400f60e01b815260040160405180910390fd5b935093915050565b606580546001600160a01b0319169055610ad481614369565b6d636861696e5f7761746368646f6760901b6130086033546001600160a01b031690565b6001600160a01b0316336001600160a01b031614158015613045575061302f816001610ffd565b6001600160a01b0316336001600160a01b031614155b156108f557604051630d85cccf60e11b815260040160405180910390fd5b61306b61498b565b60605f61307a86880188615ae1565b60208101519091506001600160a01b0316613096573360208201525b6040805160e08101825260058d01546001600160401b038082168352600160401b82048116602080850182905260ff600160801b85048116151596860196909652600160881b8404909516606085015261ffff600160901b840416608085015263ffffffff600160a01b84041660a0850152600160c01b9092041660c0830152918b015190916131269190615bb5565b613131906001615bb5565b6001600160401b0316815f01516001600160401b031610613165576040516351ec7d5360e01b815260040160405180910390fd5b5f8c5f015f8c604001516001855f015161317f9190615bd5565b61318991906156dc565b6001600160401b0316815260208101919091526040015f20546060840151909150158015906131bc575082606001518114155b156131da57604051630d41ec8760e11b815260040160405180910390fd5b604080516101c0810182525f194301804082525f60208084018290528385018290529387015160608401527f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd608080850191909152938701516001600160a01b031660a084015285516001600160401b0390811660c0850152938f015163ffffffff1660e08401524284166101008401529216610120820152610140810191909152861561016082018190526101808201839052336101a0830152909550156132f1576132a6466139ea565b6132c35760405163df9969ef60e01b815260040160405180910390fd5b5f80496040870181905290036132ec57604051639e7e2ddd60e01b815260040160405180910390fd5b613362565b8686604051613301929190615bf5565b60408051918290039091209086015260e08b015180156133445750336001600160a01b031661333886604001518560a001516143ba565b6001600160a01b031614155b156133625760405163f6ee3bdb60e01b815260040160405180910390fd5b81516040805144602082015260c09290921b6001600160c01b0319169082015243604882015260680160408051808303601f1901815291815281516020928301209187019190915251635437cecf60e11b81526a3a34b2b92fb937baba32b960a91b60048201525f60248201819052906001600160a01b038c169063a86f9d9e90604401602060405180830381865afa158015613401573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906134259190615701565b8351604051635c42d07960e01b81526001600160401b0390911660048201529091505f906001600160a01b03831690635c42d07990602401602060405180830381865afa158015613478573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061349c9190615701565b60208801516040516359ab4e2360e01b81529192506001600160a01b038316916359ab4e23916134d29160040190815260200190565b602060405180830381865afa1580156134ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135119190615c04565b61ffff1661014088015250506040805161010081019091525f908061353588613a44565b81526020015f6001600160a01b031681526020018d60a001516001600160601b03168152602001845f01516001600160401b031681526020018761010001516001600160401b03168152602001436001600160401b03168152602001600163ffffffff1681526020015f63ffffffff168152509050808e5f015f8e60400151865f01516135c291906156dc565b6001600160401b03166001600160401b031681526020019081526020015f205f820151815f01556020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160601b0302191690836001600160601b031602179055506060820151816002015f6101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160020160086101000a8154816001600160401b0302191690836001600160401b0316021790555060a08201518160020160106101000a8154816001600160401b0302191690836001600160401b0316021790555060c08201518160020160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600201601c6101000a81548163ffffffff021916908363ffffffff1602179055509050508d6005015f015f81819054906101000a90046001600160401b031660010191906101000a8154816001600160401b0302191690836001600160401b031602179055508c6001600160a01b03166323b872dd33308f60a001516040518463ffffffff1660e01b81526004016137b7939291906001600160a01b0393841681529190921660208201526001600160601b0391909116604082015260600190565b6020604051808303815f875af11580156137d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906137f7919061592a565b50341580159061380657504115155b156138155761381541346143d4565b604080515f8082526020820190925290613855565b604080516060810182525f80825260208083018290529282015282525f1990920191018161382a5790505b509450336001600160a01b03168660c001516001600160401b03167fcda4e564245eb15494bc6da29f6a42e1941cf57f5314bf35bab8a1fca0a9c60a8e60a0015189896040516138a793929190615c1f565b60405180910390a3505050509850989650505050505050565b5f805f6138ce878787612f6b565b915091505f6138df88848488614073565b90508063ffffffff165f036139075760405163727b1d6160e01b815260040160405180910390fd5b6001600160401b039091165f908152600288016020908152604080832063ffffffff909416835292905220915050949350505050565b6005820154811515600160801b90910460ff161515036139705760405163689d009d60e11b815260040160405180910390fd5b60058201805460ff60801b1916600160801b83151502179055806139b1576005820180546001600160c01b0316600160c01b426001600160401b0316021790555b60405181151581527fed64db85835d07c3c990b8ebdd55e32d64e5ed53143b6ef2179e7bfaf17ddc3b9060200160405180910390a15050565b5f60018214806139fb575061426882145b80613a08575062aa36a782145b80610d405750610d40826143df565b5f60018311613a2857506001610d40565b60018303838381613a3b57613a3b6156c8565b06149392505050565b5f81604051602001613a569190615c4f565b604051602081830303815290604052805190602001209050919050565b5f613a7c6148fd565b613a908686856101000151875f0151614073565b91508163ffffffff165f03613b5157600285018054600163ffffffff600160c01b80840482168381019092160263ffffffff60c01b1990931692909217928390556001600160401b03600160401b9093049290921660e08401529250829003613b0f578351815260a08301516001600160a01b031660608201526112bd565b6101208301516001600160401b03165f9081526001870160209081526040808320875184529091529020805463ffffffff191663ffffffff84161790556112bd565b50610100808301516001600160401b039081165f90815260028089016020908152604080842063ffffffff8816855282529283902083516101408101855281548152600182015492810192909252918201549281019290925260038101546001600160a01b0380821660608501526001600160601b03600160a01b9283900481166080860152600484015491821660a08601529190041660c08301526005015491821660e082015261ffff600160401b8304169281019290925260ff600160501b9091041661012082015294509492505050565b5f80603c8302613c3586866143f6565b0142101595945050505050565b60a08401515f906001600160a01b031615613d9357816101c0015115613d0957613c788560c001516001600160601b031661440b565b60608084015190870151608088015160405163a9059cbb60e01b81526001600160a01b0392831660048201526001600160601b039091166024820152929350169063a9059cbb906044015b6020604051808303815f875af1158015613cdf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613d03919061592a565b50613ecf565b6002613d2186608001516001600160601b031661440b565b901c905081606001516001600160a01b031663a9059cbb8660a00151836003613d4a9190615c5e565b8860c001516001600160601b0316613d629190615c75565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401613cc3565b816101c0015115613db757604051639d49773160e01b815260040160405180910390fd5b613dcd85608001516001600160601b031661440b565b90508160e001516001600160601b03165f14613ecf576001860180546001600160a01b031690556020830151613e0490839061442d565b15613ecf57336001600160a01b03168260a001516001600160a01b031603613e455760e0820151613e3e906001600160601b031682615c75565b9050613ecf565b606082015160a083015160e084015160405163a9059cbb60e01b81526001600160a01b0392831660048201526001600160601b03909116602482015291169063a9059cbb906044016020604051808303815f875af1158015613ea9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613ecd919061592a565b505b8160200151602001516001600160601b0316811115613f75576060820151602080840151015160405163a9059cbb60e01b81523360048201526001600160601b03909116830360248201526001600160a01b039091169063a9059cbb906044016020604051808303815f875af1158015613f4b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613f6f919061592a565b5061401e565b8160200151602001516001600160601b031681101561401e57606082015160208084015101516040516323b872dd60e01b81523360048201523060248201526001600160601b0390911683900360448201526001600160a01b03909116906323b872dd906064016020604051808303815f875af1158015613ff8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061401c919061592a565b505b60208083015101516001600160601b031660808601525f60a0860152336060860152825161ffff166101008601526101c082015161406b576020808501519086015260c082015160408601525b505050505050565b6001600160401b0382165f9081526002850160209081526040808320600184529091528120548290036140da57506002830154600190600160c01b900463ffffffff1681106140d5576040516367a1907f60e01b815260040160405180910390fd5b612f63565b5060028301546001600160401b03165f908152600185016020908152604080832084845290915290205463ffffffff16801580159061412e5750600284015463ffffffff600160c01b909104811690821610155b15612f63576040516367a1907f60e01b815260040160405180910390fd5b5f54610100900460ff166141725760405162461bcd60e51b81526004016106ff90615c88565b61417a61449d565b6141986001600160a01b038216156141925781612fcb565b33612fcb565b5060c9805461ff001916610100179055565b5f54610100900460ff166141d05760405162461bcd60e51b81526004016106ff90615c88565b6001600160401b034611156141f85760405163a12e8fa960e01b815260040160405180910390fd5b609780546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381163b6142875760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016106ff565b5f80516020615d3b83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6142be836144c3565b5f825111806142ca5750805b156108f5576142d98383614502565b50505050565b6142f360c954610100900460ff1660021490565b6143105760405163bae6e2a960e01b815260040160405180910390fd5b60c9805461010069ffffffffffffffffff001990911662010000426001600160401b031602171790556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602001612c43565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f805f6143c78585614527565b91509150612ec381614569565b610bcd82825a6146b2565b5f617e2c8210158015610d40575050617e90101590565b5f8183116144045781610ae6565b5090919050565b5f811561442657600361441f836007615c5e565b901c610d40565b5f92915050565b5f826101a00151801561444b575082610140015163ffffffff166001145b80610ae657508261018001518015614464575081516020145b8015610ae657507f20d34d7a20a139f9be221ba2163925c0c86ed02d34033f288f010d23a63ef4b761449583615cd3565b149392505050565b5f54610100900460ff16610e3e5760405162461bcd60e51b81526004016106ff90615c88565b6144cc8161421a565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610ae68383604051806060016040528060278152602001615d5b602791396146f5565b5f80825160410361455b576020830151604084015160608501515f1a61454f87828585614769565b94509450505050614562565b505f905060025b9250929050565b5f81600481111561457c5761457c615cf9565b036145845750565b600181600481111561459857614598615cf9565b036145e55760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e6174757265000000000000000060448201526064016106ff565b60028160048111156145f9576145f9615cf9565b036146465760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e6774680060448201526064016106ff565b600381600481111561465a5761465a615cf9565b03610ad45760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b60648201526084016106ff565b815f036146be57505050565b6146d883838360405180602001604052805f815250614823565b6108f557604051634c67134d60e11b815260040160405180910390fd5b60605f80856001600160a01b0316856040516147119190615d0d565b5f60405180830381855af49150503d805f8114614749576040519150601f19603f3d011682016040523d82523d5f602084013e61474e565b606091505b509150915061475f86838387614860565b9695505050505050565b5f807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561479e57505f905060036112bd565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156147ef573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116614817575f600192509250506112bd565b965f9650945050505050565b5f6001600160a01b03851661484b57604051634c67134d60e11b815260040160405180910390fd5b5f80835160208501878988f195945050505050565b606083156148ce5782515f036148c7576001600160a01b0385163b6148c75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106ff565b5081612f63565b612f6383838151156148e35781518083602001fd5b8060405162461bcd60e51b81526004016106ff9190615d28565b60408051610140810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040805160e0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080516101c0810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081019190915290565b604051806101e00160405280614a12614950565b81526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a082015291019081526040805160c0810182525f8082526020828101829052928201819052606082018190526080820181905260a08201529101905b81525f6020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082018190526101208201819052610140820181905261016082018190526101809091015290565b604051806101a00160405280614a7b614950565b80356001600160401b0381168114614b03575f80fd5b919050565b5f8083601f840112614b18575f80fd5b5081356001600160401b03811115614b2e575f80fd5b602083019150836020828501011115614562575f80fd5b5f805f60408486031215614b57575f80fd5b614b6084614aed565b925060208401356001600160401b03811115614b7a575f80fd5b614b8686828701614b08565b9497909650939450505050565b6001600160a01b0381168114610ad4575f80fd5b8035614b0381614b93565b8015158114610ad4575f80fd5b8035614b0381614bb2565b5f805f8060808587031215614bdd575f80fd5b8435614be881614b93565b93506020850135614bf881614b93565b9250604085013591506060850135614c0f81614bb2565b939692955090935050565b5f60208284031215614c2a575f80fd5b8135610ae681614b93565b5f805f60608486031215614c47575f80fd5b614c5084614aed565b9250602084013591506040840135614c6781614bb2565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715614ca857614ca8614c72565b60405290565b6040516101c081016001600160401b0381118282101715614ca857614ca8614c72565b60405160c081016001600160401b0381118282101715614ca857614ca8614c72565b604051601f8201601f191681016001600160401b0381118282101715614d1b57614d1b614c72565b604052919050565b5f82601f830112614d32575f80fd5b81356001600160401b03811115614d4b57614d4b614c72565b614d5e601f8201601f1916602001614cf3565b818152846020838601011115614d72575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215614d9f575f80fd5b8235614daa81614b93565b915060208301356001600160401b03811115614dc4575f80fd5b614dd085828601614d23565b9150509250929050565b803563ffffffff81168114614b03575f80fd5b5f8060408385031215614dfe575f80fd5b614e0783614aed565b9150614e1560208401614dda565b90509250929050565b5f610140820190508251825260208301516020830152604083015160408301526060830151614e5860608401826001600160a01b03169052565b506080830151614e7360808401826001600160601b03169052565b5060a0830151614e8e60a08401826001600160a01b03169052565b5060c0830151614ea960c08401826001600160601b03169052565b5060e0830151614ec460e08401826001600160401b03169052565b506101008381015161ffff16908301526101209283015160ff16929091019190915290565b5f60208284031215614ef9575f80fd5b610ae682614aed565b815181526020808301516001600160a01b0316908201526040808301516001600160601b0316908201526060808301516001600160401b039081169183019190915260808084015182169083015260a080840151918216908301526101008201905060c0830151614f7b60c084018263ffffffff169052565b5060e0830151614f9360e084018263ffffffff169052565b5092915050565b5f8060408385031215614fab575f80fd5b823591506020830135614fbd81614bb2565b809150509250929050565b6001600160401b0380825116835280602083015116602084015260408201511515604084015260ff606083015116606084015261ffff608083015116608084015263ffffffff60a08301511660a08401528060c08301511660c0840152505050565b838152610180810161506d602083018580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b612f6360a0830184614fc8565b5f610100820190506001600160401b038084511683528060208501511660208401528060408501511660408401528060608501511660608401525063ffffffff608084015116608083015260a08301516150df60a08401826001600160601b03169052565b5060c08301516150f460c084018260ff169052565b5060e0830151614f9360e084018215159052565b6101608101615145828580516001600160401b03908116835260208083015182169084015260408083015182169084015260609182015116910152565b610ae66080830184614fc8565b5f805f8060408587031215615165575f80fd5b84356001600160401b038082111561517b575f80fd5b61518788838901614b08565b9096509450602087013591508082111561519f575f80fd5b506151ac87828801614b08565b95989497509550505050565b805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a08101516151fe60a08401826001600160a01b03169052565b5060c081015161521960c08401826001600160401b03169052565b5060e081015161523160e084018263ffffffff169052565b50610100818101516001600160401b039081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015115159083015261018080820151908301526101a0808201516001600160a01b038116828501526142d9565b5f815180845260208085019450602084015f5b838110156152fa57815180516001600160a01b03168852838101516001600160601b0316848901526040908101516001600160401b031690880152606090960195908201906001016152ad565b509495945050505050565b5f6101e061531383866151b8565b806101c08401526153268184018561529a565b95945050505050565b5f8060408385031215615340575f80fd5b61534983614aed565b946020939093013593505050565b5f60208284031215615367575f80fd5b8135610ae681614bb2565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b61ffff81168114610ad4575f80fd5b8035614b03816153c0565b5f608082840312156153ea575f80fd5b604051608081018181106001600160401b038211171561540c5761540c614c72565b8060405250809150823581526020830135602082015260408301356040820152606083013560608201525092915050565b5f6040828403121561544d575f80fd5b615455614c86565b90508135615462816153c0565b815260208201356001600160401b0381111561547c575f80fd5b61548884828501614d23565b60208301525092915050565b5f805f8385036102608112156154a8575f80fd5b6101c0808212156154b7575f80fd5b6154bf614cae565b915085358252602086013560208301526040860135604083015260608601356060830152608086013560808301526154f960a08701614ba7565b60a083015261550a60c08701614aed565b60c083015261551b60e08701614dda565b60e083015261010061552e818801614aed565b90830152610120615540878201614aed565b908301526101406155528782016153cf565b90830152610160615564878201614bbf565b9083015261018086810135908301526101a0615581818801614ba7565b8184015250819450615595878288016153da565b935050506102408401356001600160401b038111156155b2575f80fd5b6155be8682870161543d565b9150509250925092565b5f60e08201905082546001600160401b038082168452808260401c1660208501525060ff8160801c161515604084015260ff8160881c16606084015261ffff8160901c16608084015263ffffffff8160a01c1660a08401528060c01c60c08401525092915050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52601260045260245ffd5b5f6001600160401b03808416806156f5576156f56156c8565b92169190910692915050565b5f60208284031215615711575f80fd5b8151610ae681614b93565b80516001600160601b0381168114614b03575f80fd5b5f60c08284031215615742575f80fd5b61574a614cd1565b8251815261575a6020840161571c565b602082015261576b6040840161571c565b6040820152606083015162ffffff81168114615785575f80fd5b60608201526080830151615798816153c0565b608082015260a083015160ff811681146157b0575f80fd5b60a08201529392505050565b5f5b838110156157d65781810151838201526020016157be565b50505f910152565b5f81518084526157f58160208601602086016157bc565b601f01601f19169290920160200192915050565b61ffff81511682525f602082015160406020850152612f6360408501826157de565b83518152602080850151818301526040808601516001600160a01b03908116828501526060808801516001600160401b03168186015260808089015115159086015260a08089015115159086015260c08089015190921691850191909152855160e0850152918501516101008401528401516101208301528301516101408201525f6101808061016084015261475f81840185615809565b845181526020808601519082015260408086015190820152606094850151948101949094526001600160a01b039290921660808401526001600160601b031660a083015261ffff1660c082015260e00190565b634e487b7160e01b5f52600160045260245ffd5b5f6020828403121561593a575f80fd5b8151610ae681614bb2565b5f82615953576159536156c8565b500690565b634e487b7160e01b5f52603260045260245ffd5b604080825283519082018190525f906020906060840190828701845b828110156159ad5781516001600160a01b031684529284019290840190600101615988565b505050838103828501528451808252858301918301905f5b818110156159e1578351835292840192918401916001016159c5565b5090979650505050505050565b5f602082840312156159fe575f80fd5b5051919050565b5f82601f830112615a14575f80fd5b813560206001600160401b0380831115615a3057615a30614c72565b8260051b615a3f838201614cf3565b9384528581018301938381019088861115615a58575f80fd5b84880192505b85831015615ad557823584811115615a74575f80fd5b88016040818b03601f1901811315615a8a575f80fd5b615a92614c86565b87830135615a9f81614b93565b8152908201359086821115615ab2575f80fd5b615ac08c8984860101614d23565b81890152845250509184019190840190615a5e565b98975050505050505050565b5f60208284031215615af1575f80fd5b81356001600160401b0380821115615b07575f80fd5b9083019060c08286031215615b1a575f80fd5b615b22614cd1565b615b2b83614ba7565b8152615b3960208401614ba7565b60208201526040830135604082015260608301356060820152608083013582811115615b63575f80fd5b615b6f87828601615a05565b60808301525060a083013582811115615b86575f80fd5b615b9287828601614d23565b60a08301525095945050505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115614f9357614f93615ba1565b6001600160401b03828116828216039080821115614f9357614f93615ba1565b818382375f9101908152919050565b5f60208284031215615c14575f80fd5b8151610ae6816153c0565b5f6102006001600160601b0386168352615c3c60208401866151b8565b806101e084015261475f8184018561529a565b6101c08101610d4082846151b8565b8082028115828204841417610d4057610d40615ba1565b80820180821115610d4057610d40615ba1565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b80516020808301519190811015615cf3575f198160200360031b1b821691505b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f8251615d1e8184602087016157bc565b9190910192915050565b602081525f610ae660208301846157de56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220326b0dffa124ebf142f195b9a1744708d52ed7369b839aedb262467ed79e2b9464736f6c63430008180033
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.