Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
1326558 | 278 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
L2OutputOracle
Compiler Version
v0.8.15+commit.e14f2714
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { ISemver } from "src/universal/ISemver.sol"; import { Types } from "src/libraries/Types.sol"; import { Constants } from "src/libraries/Constants.sol"; /// @custom:proxied /// @title L2OutputOracle /// @notice The L2OutputOracle contains an array of L2 state outputs, where each output is a /// commitment to the state of the L2 chain. Other contracts like the OptimismPortal use /// these outputs to verify information about the state of L2. contract L2OutputOracle is Initializable, ISemver { /// @notice The number of the first L2 block recorded in this contract. uint256 public startingBlockNumber; /// @notice The timestamp of the first L2 block recorded in this contract. uint256 public startingTimestamp; /// @notice An array of L2 output proposals. Types.OutputProposal[] internal l2Outputs; /// @notice The interval in L2 blocks at which checkpoints must be submitted. /// @custom:network-specific uint256 public submissionInterval; /// @notice The time between L2 blocks in seconds. Once set, this value MUST NOT be modified. /// @custom:network-specific uint256 public l2BlockTime; /// @notice The address of the challenger. Can be updated via upgrade. /// @custom:network-specific address public challenger; /// @notice The address of the proposer. Can be updated via upgrade. /// @custom:network-specific address public proposer; /// @notice The minimum time (in seconds) that must elapse before a withdrawal can be finalized. /// @custom:network-specific uint256 public finalizationPeriodSeconds; /// @notice Emitted when an output is proposed. /// @param outputRoot The output root. /// @param l2OutputIndex The index of the output in the l2Outputs array. /// @param l2BlockNumber The L2 block number of the output root. /// @param l1Timestamp The L1 timestamp when proposed. event OutputProposed( bytes32 indexed outputRoot, uint256 indexed l2OutputIndex, uint256 indexed l2BlockNumber, uint256 l1Timestamp ); /// @notice Emitted when outputs are deleted. /// @param prevNextOutputIndex Next L2 output index before the deletion. /// @param newNextOutputIndex Next L2 output index after the deletion. event OutputsDeleted(uint256 indexed prevNextOutputIndex, uint256 indexed newNextOutputIndex); /// @notice Semantic version. /// @custom:semver 1.8.0 string public constant version = "1.8.0"; /// @notice Constructs the L2OutputOracle contract. Initializes variables to the same values as /// in the getting-started config. constructor() { initialize({ _submissionInterval: 1, _l2BlockTime: 1, _startingBlockNumber: 0, _startingTimestamp: 0, _proposer: address(0), _challenger: address(0), _finalizationPeriodSeconds: 0 }); } /// @notice Initializer. /// @param _submissionInterval Interval in blocks at which checkpoints must be submitted. /// @param _l2BlockTime The time per L2 block, in seconds. /// @param _startingBlockNumber The number of the first L2 block. /// @param _startingTimestamp The timestamp of the first L2 block. /// @param _proposer The address of the proposer. /// @param _challenger The address of the challenger. /// @param _finalizationPeriodSeconds The minimum time (in seconds) that must elapse before a withdrawal /// can be finalized. function initialize( uint256 _submissionInterval, uint256 _l2BlockTime, uint256 _startingBlockNumber, uint256 _startingTimestamp, address _proposer, address _challenger, uint256 _finalizationPeriodSeconds ) public initializer { require(_submissionInterval > 0, "L2OutputOracle: submission interval must be greater than 0"); require(_l2BlockTime > 0, "L2OutputOracle: L2 block time must be greater than 0"); require( _startingTimestamp <= block.timestamp, "L2OutputOracle: starting L2 timestamp must be less than current time" ); submissionInterval = _submissionInterval; l2BlockTime = _l2BlockTime; startingBlockNumber = _startingBlockNumber; startingTimestamp = _startingTimestamp; proposer = _proposer; challenger = _challenger; finalizationPeriodSeconds = _finalizationPeriodSeconds; } /// @notice Getter for the submissionInterval. /// Public getter is legacy and will be removed in the future. Use `submissionInterval` instead. /// @return Submission interval. /// @custom:legacy function SUBMISSION_INTERVAL() external view returns (uint256) { return submissionInterval; } /// @notice Getter for the l2BlockTime. /// Public getter is legacy and will be removed in the future. Use `l2BlockTime` instead. /// @return L2 block time. /// @custom:legacy function L2_BLOCK_TIME() external view returns (uint256) { return l2BlockTime; } /// @notice Getter for the challenger address. /// Public getter is legacy and will be removed in the future. Use `challenger` instead. /// @return Address of the challenger. /// @custom:legacy function CHALLENGER() external view returns (address) { return challenger; } /// @notice Getter for the proposer address. /// Public getter is legacy and will be removed in the future. Use `proposer` instead. /// @return Address of the proposer. /// @custom:legacy function PROPOSER() external view returns (address) { return proposer; } /// @notice Getter for the finalizationPeriodSeconds. /// Public getter is legacy and will be removed in the future. Use `finalizationPeriodSeconds` instead. /// @return Finalization period in seconds. /// @custom:legacy function FINALIZATION_PERIOD_SECONDS() external view returns (uint256) { return finalizationPeriodSeconds; } /// @notice Deletes all output proposals after and including the proposal that corresponds to /// the given output index. Only the challenger address can delete outputs. /// @param _l2OutputIndex Index of the first L2 output to be deleted. /// All outputs after this output will also be deleted. // solhint-disable-next-line ordering function deleteL2Outputs(uint256 _l2OutputIndex) external { require(msg.sender == challenger, "L2OutputOracle: only the challenger address can delete outputs"); // Make sure we're not *increasing* the length of the array. require( _l2OutputIndex < l2Outputs.length, "L2OutputOracle: cannot delete outputs after the latest output index" ); // Do not allow deleting any outputs that have already been finalized. require( block.timestamp - l2Outputs[_l2OutputIndex].timestamp < finalizationPeriodSeconds, "L2OutputOracle: cannot delete outputs that have already been finalized" ); uint256 prevNextL2OutputIndex = nextOutputIndex(); // Use assembly to delete the array elements because Solidity doesn't allow it. assembly { sstore(l2Outputs.slot, _l2OutputIndex) } emit OutputsDeleted(prevNextL2OutputIndex, _l2OutputIndex); } /// @notice Accepts an outputRoot and the timestamp of the corresponding L2 block. /// The timestamp must be equal to the current value returned by `nextTimestamp()` in /// order to be accepted. This function may only be called by the Proposer. /// @param _outputRoot The L2 output of the checkpoint block. /// @param _l2BlockNumber The L2 block number that resulted in _outputRoot. /// @param _l1BlockHash A block hash which must be included in the current chain. /// @param _l1BlockNumber The block number with the specified block hash. function proposeL2Output( bytes32 _outputRoot, uint256 _l2BlockNumber, bytes32 _l1BlockHash, uint256 _l1BlockNumber ) external payable { require(msg.sender == proposer, "L2OutputOracle: only the proposer address can propose new outputs"); require( _l2BlockNumber == nextBlockNumber(), "L2OutputOracle: block number must be equal to next expected block number" ); require( computeL2Timestamp(_l2BlockNumber) < block.timestamp, "L2OutputOracle: cannot propose L2 output in the future" ); require(_outputRoot != bytes32(0), "L2OutputOracle: L2 output proposal cannot be the zero hash"); if (_l1BlockHash != bytes32(0)) { // This check allows the proposer to propose an output based on a given L1 block, // without fear that it will be reorged out. // It will also revert if the blockheight provided is more than 256 blocks behind the // chain tip (as the hash will return as zero). This does open the door to a griefing // attack in which the proposer's submission is censored until the block is no longer // retrievable, if the proposer is experiencing this attack it can simply leave out the // blockhash value, and delay submission until it is confident that the L1 block is // finalized. require( blockhash(_l1BlockNumber) == _l1BlockHash, "L2OutputOracle: block hash does not match the hash at the expected height" ); } emit OutputProposed(_outputRoot, nextOutputIndex(), _l2BlockNumber, block.timestamp); l2Outputs.push( Types.OutputProposal({ outputRoot: _outputRoot, timestamp: uint128(block.timestamp), l2BlockNumber: uint128(_l2BlockNumber) }) ); } /// @notice Returns an output by index. Needed to return a struct instead of a tuple. /// @param _l2OutputIndex Index of the output to return. /// @return The output at the given index. function getL2Output(uint256 _l2OutputIndex) external view returns (Types.OutputProposal memory) { return l2Outputs[_l2OutputIndex]; } /// @notice Returns the index of the L2 output that checkpoints a given L2 block number. /// Uses a binary search to find the first output greater than or equal to the given /// block. /// @param _l2BlockNumber L2 block number to find a checkpoint for. /// @return Index of the first checkpoint that commits to the given L2 block number. function getL2OutputIndexAfter(uint256 _l2BlockNumber) public view returns (uint256) { // Make sure an output for this block number has actually been proposed. require( _l2BlockNumber <= latestBlockNumber(), "L2OutputOracle: cannot get output for a block that has not been proposed" ); // Make sure there's at least one output proposed. require(l2Outputs.length > 0, "L2OutputOracle: cannot get output as no outputs have been proposed yet"); // Find the output via binary search, guaranteed to exist. uint256 lo = 0; uint256 hi = l2Outputs.length; while (lo < hi) { uint256 mid = (lo + hi) / 2; if (l2Outputs[mid].l2BlockNumber < _l2BlockNumber) { lo = mid + 1; } else { hi = mid; } } return lo; } /// @notice Returns the L2 output proposal that checkpoints a given L2 block number. /// Uses a binary search to find the first output greater than or equal to the given /// block. /// @param _l2BlockNumber L2 block number to find a checkpoint for. /// @return First checkpoint that commits to the given L2 block number. function getL2OutputAfter(uint256 _l2BlockNumber) external view returns (Types.OutputProposal memory) { return l2Outputs[getL2OutputIndexAfter(_l2BlockNumber)]; } /// @notice Returns the number of outputs that have been proposed. /// Will revert if no outputs have been proposed yet. /// @return The number of outputs that have been proposed. function latestOutputIndex() external view returns (uint256) { return l2Outputs.length - 1; } /// @notice Returns the index of the next output to be proposed. /// @return The index of the next output to be proposed. function nextOutputIndex() public view returns (uint256) { return l2Outputs.length; } /// @notice Returns the block number of the latest submitted L2 output proposal. /// If no proposals been submitted yet then this function will return the starting /// block number. /// @return Latest submitted L2 block number. function latestBlockNumber() public view returns (uint256) { return l2Outputs.length == 0 ? startingBlockNumber : l2Outputs[l2Outputs.length - 1].l2BlockNumber; } /// @notice Computes the block number of the next L2 block that needs to be checkpointed. /// @return Next L2 block number. function nextBlockNumber() public view returns (uint256) { return latestBlockNumber() + submissionInterval; } /// @notice Returns the L2 timestamp corresponding to a given L2 block number. /// @param _l2BlockNumber The L2 block number of the target block. /// @return L2 timestamp of the given block. function computeL2Timestamp(uint256 _l2BlockNumber) public view returns (uint256) { return startingTimestamp + ((_l2BlockNumber - startingBlockNumber) * l2BlockTime); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/Address.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] * ``` * 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. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.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. * * `initializer` is equivalent to `reinitializer(1)`, so 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. * * 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. */ 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. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title ISemver /// @notice ISemver is a simple contract for ensuring that contracts are /// versioned using semantic versioning. interface ISemver { /// @notice Getter for the semantic version of the contract. This is not /// meant to be used onchain but instead meant to be used by offchain /// tooling. /// @return Semver contract version as a string. function version() external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Types /// @notice Contains various types used throughout the Optimism contract system. library Types { /// @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1 /// timestamp that the output root is posted. This timestamp is used to verify that the /// finalization period has passed since the output root was submitted. /// @custom:field outputRoot Hash of the L2 output. /// @custom:field timestamp Timestamp of the L1 block that the output root was submitted in. /// @custom:field l2BlockNumber L2 block number that the output corresponds to. struct OutputProposal { bytes32 outputRoot; uint128 timestamp; uint128 l2BlockNumber; } /// @notice Struct representing the elements that are hashed together to generate an output root /// which itself represents a snapshot of the L2 state. /// @custom:field version Version of the output root. /// @custom:field stateRoot Root of the state trie at the block of this output. /// @custom:field messagePasserStorageRoot Root of the message passer storage trie. /// @custom:field latestBlockhash Hash of the block this output was generated from. struct OutputRootProof { bytes32 version; bytes32 stateRoot; bytes32 messagePasserStorageRoot; bytes32 latestBlockhash; } /// @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end /// user (as opposed to a system deposit transaction generated by the system). /// @custom:field from Address of the sender of the transaction. /// @custom:field to Address of the recipient of the transaction. /// @custom:field isCreation True if the transaction is a contract creation. /// @custom:field value Value to send to the recipient. /// @custom:field mint Amount of ETH to mint. /// @custom:field gasLimit Gas limit of the transaction. /// @custom:field data Data of the transaction. /// @custom:field l1BlockHash Hash of the block the transaction was submitted in. /// @custom:field logIndex Index of the log in the block the transaction was submitted in. struct UserDepositTransaction { address from; address to; bool isCreation; uint256 value; uint256 mint; uint64 gasLimit; bytes data; bytes32 l1BlockHash; uint256 logIndex; } /// @notice Struct representing a withdrawal transaction. /// @custom:field nonce Nonce of the withdrawal transaction /// @custom:field sender Address of the sender of the transaction. /// @custom:field target Address of the recipient of the transaction. /// @custom:field value Value to send to the recipient. /// @custom:field gasLimit Gas limit of the transaction. /// @custom:field data Data of the transaction. struct WithdrawalTransaction { uint256 nonce; address sender; address target; uint256 value; uint256 gasLimit; bytes data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; /// @title Constants /// @notice Constants is a library for storing constants. Simple! Don't put everything in here, just /// the stuff used in multiple contracts. Constants that only apply to a single contract /// should be defined in that contract instead. library Constants { /// @notice Special address to be used as the tx origin for gas estimation calls in the /// OptimismPortal and CrossDomainMessenger calls. You only need to use this address if /// the minimum gas limit specified by the user is not actually enough to execute the /// given message and you're attempting to estimate the actual necessary gas limit. We /// use address(1) because it's the ecrecover precompile and therefore guaranteed to /// never have any code on any EVM chain. address internal constant ESTIMATION_ADDRESS = address(1); /// @notice Value used for the L2 sender storage slot in both the OptimismPortal and the /// CrossDomainMessenger contracts before an actual sender is set. This value is /// non-zero to reduce the gas cost of message passing transactions. address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; /// @notice The storage slot that holds the address of a proxy implementation. /// @dev `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)` bytes32 internal constant PROXY_IMPLEMENTATION_ADDRESS = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /// @notice The storage slot that holds the address of the owner. /// @dev `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)` bytes32 internal constant PROXY_OWNER_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /// @notice Returns the default values for the ResourceConfig. These are the recommended values /// for a production network. function DEFAULT_RESOURCE_CONFIG() internal pure returns (ResourceMetering.ResourceConfig memory) { ResourceMetering.ResourceConfig memory config = ResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, elasticityMultiplier: 10, baseFeeMaxChangeDenominator: 8, minimumBaseFee: 1 gwei, systemTxMaxGas: 1_000_000, maximumBaseFee: type(uint128).max }); return config; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.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 * ==== * * [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://diligence.consensys.net/posts/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.5.11/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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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 pragma solidity 0.8.15; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Burn } from "src/libraries/Burn.sol"; import { Arithmetic } from "src/libraries/Arithmetic.sol"; /// @custom:upgradeable /// @title ResourceMetering /// @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing /// updates automatically based on current demand. abstract contract ResourceMetering is Initializable { /// @notice Represents the various parameters that control the way in which resources are /// metered. Corresponds to the EIP-1559 resource metering system. /// @custom:field prevBaseFee Base fee from the previous block(s). /// @custom:field prevBoughtGas Amount of gas bought so far in the current block. /// @custom:field prevBlockNum Last block number that the base fee was updated. struct ResourceParams { uint128 prevBaseFee; uint64 prevBoughtGas; uint64 prevBlockNum; } /// @notice Represents the configuration for the EIP-1559 based curve for the deposit gas /// market. These values should be set with care as it is possible to set them in /// a way that breaks the deposit gas market. The target resource limit is defined as /// maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a /// single word. There is additional space for additions in the future. /// @custom:field maxResourceLimit Represents the maximum amount of deposit gas that /// can be purchased per block. /// @custom:field elasticityMultiplier Determines the target resource limit along with /// the resource limit. /// @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block. /// @custom:field minimumBaseFee The min deposit base fee, it is clamped to this /// value. /// @custom:field systemTxMaxGas The amount of gas supplied to the system /// transaction. This should be set to the same /// number that the op-node sets as the gas limit /// for the system transaction. /// @custom:field maximumBaseFee The max deposit base fee, it is clamped to this /// value. struct ResourceConfig { uint32 maxResourceLimit; uint8 elasticityMultiplier; uint8 baseFeeMaxChangeDenominator; uint32 minimumBaseFee; uint32 systemTxMaxGas; uint128 maximumBaseFee; } /// @notice EIP-1559 style gas parameters. ResourceParams public params; /// @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades. uint256[48] private __gap; /// @notice Meters access to a function based an amount of a requested resource. /// @param _amount Amount of the resource requested. modifier metered(uint64 _amount) { // Record initial gas amount so we can refund for it later. uint256 initialGas = gasleft(); // Run the underlying function. _; // Run the metering function. _metered(_amount, initialGas); } /// @notice An internal function that holds all of the logic for metering a resource. /// @param _amount Amount of the resource requested. /// @param _initialGas The amount of gas before any modifier execution. function _metered(uint64 _amount, uint256 _initialGas) internal { // Update block number and base fee if necessary. uint256 blockDiff = block.number - params.prevBlockNum; ResourceConfig memory config = _resourceConfig(); int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) / int256(uint256(config.elasticityMultiplier)); if (blockDiff > 0) { // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate // at which deposits can be created and therefore limit the potential for deposits to // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes. int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit; int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) / (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator))); // Update base fee by adding the base fee delta and clamp the resulting value between // min and max. int256 newBaseFee = Arithmetic.clamp({ _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta, _min: int256(uint256(config.minimumBaseFee)), _max: int256(uint256(config.maximumBaseFee)) }); // If we skipped more than one block, we also need to account for every empty block. // Empty block means there was no demand for deposits in that block, so we should // reflect this lack of demand in the fee. if (blockDiff > 1) { // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator) // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value // between min and max. newBaseFee = Arithmetic.clamp({ _value: Arithmetic.cdexp({ _coefficient: newBaseFee, _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)), _exponent: int256(blockDiff - 1) }), _min: int256(uint256(config.minimumBaseFee)), _max: int256(uint256(config.maximumBaseFee)) }); } // Update new base fee, reset bought gas, and update block number. params.prevBaseFee = uint128(uint256(newBaseFee)); params.prevBoughtGas = 0; params.prevBlockNum = uint64(block.number); } // Make sure we can actually buy the resource amount requested by the user. params.prevBoughtGas += _amount; require( int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)), "ResourceMetering: cannot buy more gas than available gas limit" ); // Determine the amount of ETH to be paid. uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee); // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei // during any 1 day period in the last 5 years, so should be fine. uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei); // Give the user a refund based on the amount of gas they used to do all of the work up to // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts // effectively like a dynamic stipend (with a minimum value). uint256 usedGas = _initialGas - gasleft(); if (gasCost > usedGas) { Burn.gas(gasCost - usedGas); } } /// @notice Virtual function that returns the resource config. /// Contracts that inherit this contract must implement this function. /// @return ResourceConfig function _resourceConfig() internal virtual returns (ResourceConfig memory); /// @notice Sets initial resource parameter values. /// This function must either be called by the initializer function of an upgradeable /// child contract. // solhint-disable-next-line func-name-mixedcase function __ResourceMetering_init() internal onlyInitializing { if (params.prevBlockNum == 0) { params = ResourceParams({ prevBaseFee: 1 gwei, prevBoughtGas: 0, prevBlockNum: uint64(block.number) }); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.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) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 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. It 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)`. // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a // good first aproximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1; uint256 x = a; if (x >> 128 > 0) { x >>= 128; result <<= 64; } if (x >> 64 > 0) { x >>= 64; result <<= 32; } if (x >> 32 > 0) { x >>= 32; result <<= 16; } if (x >> 16 > 0) { x >>= 16; result <<= 8; } if (x >> 8 > 0) { x >>= 8; result <<= 4; } if (x >> 4 > 0) { x >>= 4; result <<= 2; } if (x >> 2 > 0) { result <<= 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) { uint256 result = sqrt(a); if (rounding == Rounding.Up && result * result < a) { result += 1; } return result; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; /// @title Burn /// @notice Utilities for burning stuff. library Burn { /// @notice Burns a given amount of ETH. /// @param _amount Amount of ETH to burn. function eth(uint256 _amount) internal { new Burner{ value: _amount }(); } /// @notice Burns a given amount of gas. /// @param _amount Amount of gas to burn. function gas(uint256 _amount) internal view { uint256 i = 0; uint256 initialGas = gasleft(); while (initialGas - gasleft() < _amount) { ++i; } } } /// @title Burner /// @notice Burner self-destructs on creation and sends all ETH to itself, removing all ETH given to /// the contract from the circulating supply. Self-destructing is the only way to remove ETH /// from the circulating supply. contract Burner { constructor() payable { selfdestruct(payable(address(this))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { SignedMath } from "@openzeppelin/contracts/utils/math/SignedMath.sol"; import { FixedPointMathLib } from "@rari-capital/solmate/src/utils/FixedPointMathLib.sol"; /// @title Arithmetic /// @notice Even more math than before. library Arithmetic { /// @notice Clamps a value between a minimum and maximum. /// @param _value The value to clamp. /// @param _min The minimum value. /// @param _max The maximum value. /// @return The clamped value. function clamp(int256 _value, int256 _min, int256 _max) internal pure returns (int256) { return SignedMath.min(SignedMath.max(_value, _min), _max); } /// @notice (c)oefficient (d)enominator (exp)onentiation function. /// Returns the result of: c * (1 - 1/d)^exp. /// @param _coefficient Coefficient of the function. /// @param _denominator Fractional denominator. /// @param _exponent Power function exponent. /// @return Result of c * (1 - 1/d)^exp. function cdexp(int256 _coefficient, int256 _denominator, int256 _exponent) internal pure returns (int256) { return (_coefficient * (FixedPointMathLib.powWad(1e18 - (1e18 / _denominator), _exponent * 1e18))) / 1e18; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.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.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } function powWad(int256 x, int256 y) internal pure returns (int256) { // Equivalent to x to the power of y because x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y) return expWad((lnWad(x) * y) / int256(WAD)); // Using ln(x) means x must be greater than 0. } function expWad(int256 x) internal pure returns (int256 r) { unchecked { // When the result is < 0.5 we return zero. This happens when // x <= floor(log(0.5e18) * 1e18) ~ -42e18 if (x <= -42139678854452767551) return 0; // When the result is > (2**255 - 1) / 1e18 we can not represent it as an // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135. if (x >= 135305999368893231589) revert("EXP_OVERFLOW"); // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 // for more intermediate precision and a binary basis. This base conversion // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5**18; // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers // of two such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96; x = x - k * 54916777467707473351141471128; // k is in the range [-61, 195]. // Evaluate using a (6, 7)-term rational approximation. // p is made monic, we'll multiply by a scale factor later. int256 y = x + 1346386616545796478920950773328; y = ((y * x) >> 96) + 57155421227552351082224309758442; int256 p = y + x - 94201549194550492254356042504812; p = ((p * y) >> 96) + 28719021644029726153956944680412240; p = p * x + (4385272521454847904659076985693276 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. int256 q = x - 2855989394907223263936484059900; q = ((q * x) >> 96) + 50020603652535783019961831881945; q = ((q * x) >> 96) - 533845033583426703283633433725380; q = ((q * x) >> 96) + 3604857256930695427073651918091429; q = ((q * x) >> 96) - 14423608567350463180887372962807573; q = ((q * x) >> 96) + 26449188498355588339934803723976023; assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial won't have zeros in the domain as all its roots are complex. // No scaling is necessary because p is already 2**96 too large. r := sdiv(p, q) } // r should be in the range (0.09, 0.25) * 2**96. // We now need to multiply r by: // * the scale factor s = ~6.031367120. // * the 2**k factor from the range reduction. // * the 1e18 / 2**96 factor for base conversion. // We do this all at once, with an intermediate result in 2**213 // basis, so the final right shift is always by a positive amount. r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)); } } function lnWad(int256 x) internal pure returns (int256 r) { unchecked { require(x > 0, "UNDEFINED"); // We want to convert x from 10**18 fixed point to 2**96 fixed point. // We do this by multiplying by 2**96 / 10**18. But since // ln(x * C) = ln(x) + ln(C), we can simply do nothing here // and add ln(2**96 / 10**18) at the end. // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) int256 k = int256(log2(uint256(x))) - 96; x <<= uint256(159 - k); x = int256(uint256(x) >> 159); // Evaluate using a (8, 8)-term rational approximation. // p is made monic, we will multiply by a scale factor later. int256 p = x + 3273285459638523848632254066296; p = ((p * x) >> 96) + 24828157081833163892658089445524; p = ((p * x) >> 96) + 43456485725739037958740375743393; p = ((p * x) >> 96) - 11111509109440967052023855526967; p = ((p * x) >> 96) - 45023709667254063763336534515857; p = ((p * x) >> 96) - 14706773417378608786704636184526; p = p * x - (795164235651350426258249787498 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. // q is monic by convention. int256 q = x + 5573035233440673466300451813936; q = ((q * x) >> 96) + 71694874799317883764090561454958; q = ((q * x) >> 96) + 283447036172924575727196451306956; q = ((q * x) >> 96) + 401686690394027663651624208769553; q = ((q * x) >> 96) + 204048457590392012362485061816622; q = ((q * x) >> 96) + 31853899698501571402653359427138; q = ((q * x) >> 96) + 909429971244387300277376558375; assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already 2**96 too large. r := sdiv(p, q) } // r is in the range (0, 0.125) * 2**96 // Finalization, we need to: // * multiply by the scale factor s = 5.549… // * add ln(2**96 / 10**18) // * add k * ln(2) // * multiply by 10**18 / 2**96 = 5**18 >> 78 // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 r *= 1677202110996718588342820967067443963516166; // add ln(2) * k * 5e18 * 2**192 r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k; // add ln(2**96 / 10**18) * 5e18 * 2**192 r += 600920179829731861736702779321621459595472258049074101567377883020018308; // base conversion: mul 2**18 / 2**192 r >>= 174; } } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // First, divide z - 1 by the denominator and add 1. // We allow z - 1 to underflow if z is 0, because we multiply the // end result by 0 if z is zero, ensuring we return 0 if z is zero. z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function log2(uint256 x) internal pure returns (uint256 r) { require(x > 0, "UNDEFINED"); assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) r := or(r, shl(2, lt(0xf, shr(r, x)))) r := or(r, shl(1, lt(0x3, shr(r, x)))) r := or(r, lt(0x1, shr(r, x))) } } }
{ "remappings": [ "@eth-optimism-bedrock/=lib/optimism/packages/contracts-bedrock/", "@fraxchain-contracts/=lib/fraxchain-contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "safe-contracts/=lib/optimism/packages/contracts-bedrock/lib/safe-contracts/contracts/", "forge-std/=lib/optimism/packages/contracts-bedrock/lib/forge-std/src/", "lib/optimism/packages/contracts-bedrock:src/=lib/optimism/packages/contracts-bedrock/src/", "lib/optimism/packages/contracts-bedrock:scripts/=lib/optimism/packages/contracts-bedrock/scripts/", "lib/optimism/packages/contracts-bedrock:@rari-capital/=lib/optimism/packages/contracts-bedrock/lib/", "lib/optimism/packages/contracts-bedrock:@cwia/=lib/optimism/packages/contracts-bedrock/lib/clones-with-immutable-args/src/", "lib/optimism/packages/contracts-bedrock:@lib-keccak/=lib/optimism/packages/contracts-bedrock/lib/lib-keccak/contracts/lib/", "lib/optimism/packages/contracts-bedrock:ds-test/=lib/optimism/packages/contracts-bedrock/lib/forge-std/lib/ds-test/src/", "lib/optimism/packages/contracts-bedrock:kontrol-cheatcodes/=lib/optimism/packages/contracts-bedrock/lib/kontrol-cheatcodes/src/", "lib/optimism/packages/contracts-bedrock:solady/=lib/optimism/packages/contracts-bedrock/lib/solady/src/", "lib/fraxchain-contracts:frax-std/=lib/fraxchain-contracts/lib/frax-standard-solidity/src/", "lib/fraxchain-contracts:@eth-optimism/=lib/optimism/packages/", "@eth-optimism/=lib/fraxchain-contracts/lib/optimism/packages/", "@openzeppelin-4/=lib/fraxchain-contracts/node_modules/@openzeppelin-4/", "@openzeppelin-5/=lib/fraxchain-contracts/node_modules/@openzeppelin-5/", "@rari-capital/=lib/fraxchain-contracts/node_modules/@rari-capital/", "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "ds-test/=lib/clones-with-immutable-args/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "frax-standard-solidity/=lib/fraxchain-contracts/lib/frax-standard-solidity/src/", "frax-std/=lib/fraxchain-contracts/lib/frax-standard-solidity/src/", "fraxchain-contracts/=lib/fraxchain-contracts/src/", "kontrol-cheatcodes/=lib/optimism/packages/contracts-bedrock/lib/kontrol-cheatcodes/src/", "lib-keccak/=lib/optimism/packages/contracts-bedrock/lib/lib-keccak/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "optimism/=lib/optimism/", "solady/=lib/optimism/packages/contracts-bedrock/lib/solady/", "solidity-bytes-utils/=lib/fraxchain-contracts/lib/frax-standard-solidity/lib/solidity-bytes-utils/", "solmate/=lib/solmate/src/", "src/=lib/fraxchain-contracts/src/" ], "optimizer": { "enabled": true, "runs": 50000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "london", "viaIR": false, "libraries": {} }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"outputRoot","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"l2OutputIndex","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"l2BlockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"l1Timestamp","type":"uint256"}],"name":"OutputProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"prevNextOutputIndex","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newNextOutputIndex","type":"uint256"}],"name":"OutputsDeleted","type":"event"},{"inputs":[],"name":"CHALLENGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FINALIZATION_PERIOD_SECONDS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L2_BLOCK_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBMISSION_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"challenger","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"}],"name":"computeL2Timestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2OutputIndex","type":"uint256"}],"name":"deleteL2Outputs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalizationPeriodSeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2OutputIndex","type":"uint256"}],"name":"getL2Output","outputs":[{"components":[{"internalType":"bytes32","name":"outputRoot","type":"bytes32"},{"internalType":"uint128","name":"timestamp","type":"uint128"},{"internalType":"uint128","name":"l2BlockNumber","type":"uint128"}],"internalType":"struct Types.OutputProposal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"}],"name":"getL2OutputAfter","outputs":[{"components":[{"internalType":"bytes32","name":"outputRoot","type":"bytes32"},{"internalType":"uint128","name":"timestamp","type":"uint128"},{"internalType":"uint128","name":"l2BlockNumber","type":"uint128"}],"internalType":"struct Types.OutputProposal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"}],"name":"getL2OutputIndexAfter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_submissionInterval","type":"uint256"},{"internalType":"uint256","name":"_l2BlockTime","type":"uint256"},{"internalType":"uint256","name":"_startingBlockNumber","type":"uint256"},{"internalType":"uint256","name":"_startingTimestamp","type":"uint256"},{"internalType":"address","name":"_proposer","type":"address"},{"internalType":"address","name":"_challenger","type":"address"},{"internalType":"uint256","name":"_finalizationPeriodSeconds","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l2BlockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestOutputIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextOutputIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_outputRoot","type":"bytes32"},{"internalType":"uint256","name":"_l2BlockNumber","type":"uint256"},{"internalType":"bytes32","name":"_l1BlockHash","type":"bytes32"},{"internalType":"uint256","name":"_l1BlockNumber","type":"uint256"}],"name":"proposeL2Output","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"proposer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startingTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"submissionInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50620000256001806000808080806200002b565b62000328565b600054610100900460ff16158080156200004c5750600054600160ff909116105b806200007c575062000069306200031960201b6200135d1760201c565b1580156200007c575060005460ff166001145b620000e55760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000109576000805461ff0019166101001790555b60008811620001815760405162461bcd60e51b815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e20300000000000006064820152608401620000dc565b60008711620001f95760405162461bcd60e51b815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e20300000000000000000000000006064820152608401620000dc565b428511156200027f5760405162461bcd60e51b8152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201526374696d6560e01b608482015260a401620000dc565b6004889055600587905560018690556002859055600780546001600160a01b038087166001600160a01b0319928316179092556006805492861692909116919091179055600882905580156200030f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6001600160a01b03163b151590565b6115fe80620003386000396000f3fe60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea2646970667358221220edf501b5b7dcf4c5e19b983dda098fcc35eb5250ade1df49e11ac69ef4b6059564736f6c634300080f0033
Deployed Bytecode
0x60806040526004361061018a5760003560e01c806389c44cbb116100d6578063ce5db8d61161007f578063dcec334811610059578063dcec33481461049b578063e1a41bcf146104b0578063f4daa291146104c657600080fd5b8063ce5db8d614610445578063cf8e5cf01461045b578063d1de856c1461047b57600080fd5b8063a25ae557116100b0578063a25ae55714610391578063a8e4fb90146103ed578063bffa7f0f1461041a57600080fd5b806389c44cbb1461034857806393991af3146103685780639aaab6481461037e57600080fd5b806369f16eec1161013857806370872aa51161011257806370872aa5146102fc5780637f00642014610312578063887862721461033257600080fd5b806369f16eec146102a75780636abcf563146102bc5780636b4d98dd146102d157600080fd5b8063529933df11610169578063529933df146101ea578063534db0e2146101ff57806354fd4d501461025157600080fd5b80622134cc1461018f5780631c89c97d146101b35780634599c788146101d5575b600080fd5b34801561019b57600080fd5b506005545b6040519081526020015b60405180910390f35b3480156101bf57600080fd5b506101d36101ce3660046113a2565b6104db565b005b3480156101e157600080fd5b506101a06108b6565b3480156101f657600080fd5b506004546101a0565b34801561020b57600080fd5b5060065461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101aa565b34801561025d57600080fd5b5061029a6040518060400160405280600581526020017f312e382e3000000000000000000000000000000000000000000000000000000081525081565b6040516101aa9190611405565b3480156102b357600080fd5b506101a0610929565b3480156102c857600080fd5b506003546101a0565b3480156102dd57600080fd5b5060065473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561030857600080fd5b506101a060015481565b34801561031e57600080fd5b506101a061032d366004611478565b61093b565b34801561033e57600080fd5b506101a060025481565b34801561035457600080fd5b506101d3610363366004611478565b610b4f565b34801561037457600080fd5b506101a060055481565b6101d361038c366004611491565b610de9565b34801561039d57600080fd5b506103b16103ac366004611478565b61124a565b60408051825181526020808401516fffffffffffffffffffffffffffffffff9081169183019190915292820151909216908201526060016101aa565b3480156103f957600080fd5b5060075461022c9073ffffffffffffffffffffffffffffffffffffffff1681565b34801561042657600080fd5b5060075473ffffffffffffffffffffffffffffffffffffffff1661022c565b34801561045157600080fd5b506101a060085481565b34801561046757600080fd5b506103b1610476366004611478565b6112de565b34801561048757600080fd5b506101a0610496366004611478565b611316565b3480156104a757600080fd5b506101a0611346565b3480156104bc57600080fd5b506101a060045481565b3480156104d257600080fd5b506008546101a0565b600054610100900460ff16158080156104fb5750600054600160ff909116105b806105155750303b158015610515575060005460ff166001145b6105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561060457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b60008811610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a207375626d697373696f6e20696e74657260448201527f76616c206d7573742062652067726561746572207468616e2030000000000000606482015260840161059d565b60008711610724576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f4c324f75747075744f7261636c653a204c3220626c6f636b2074696d65206d7560448201527f73742062652067726561746572207468616e2030000000000000000000000000606482015260840161059d565b428511156107db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526044602482018190527f4c324f75747075744f7261636c653a207374617274696e67204c322074696d65908201527f7374616d70206d757374206265206c657373207468616e2063757272656e742060648201527f74696d6500000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60048890556005879055600186905560028590556007805473ffffffffffffffffffffffffffffffffffffffff8087167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092556006805492861692909116919091179055600882905580156108ac57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6003546000901561092057600380546108d1906001906114f2565b815481106108e1576108e1611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16919050565b6001545b905090565b600354600090610924906001906114f2565b60006109456108b6565b8211156109fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f7420666f72206120626c6f636b207468617420686173206e6f74206265656e2060648201527f70726f706f736564000000000000000000000000000000000000000000000000608482015260a40161059d565b600354610aaf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f7420676574206f7574707560448201527f74206173206e6f206f7574707574732068617665206265656e2070726f706f7360648201527f6564207965740000000000000000000000000000000000000000000000000000608482015260a40161059d565b6003546000905b80821015610b485760006002610acc8385611538565b610ad69190611550565b90508460038281548110610aec57610aec611509565b600091825260209091206002909102016001015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff161015610b3e57610b37816001611538565b9250610b42565b8091505b50610ab6565b5092915050565b60065473ffffffffffffffffffffffffffffffffffffffff163314610bf6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324f75747075744f7261636c653a206f6e6c7920746865206368616c6c656e60448201527f67657220616464726573732063616e2064656c657465206f7574707574730000606482015260840161059d565b6003548110610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f747075747320616674657220746865206c6174657374206f757470757420696e60648201527f6465780000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b60085460038281548110610cc357610cc3611509565b6000918252602090912060016002909202010154610cf3906fffffffffffffffffffffffffffffffff16426114f2565b10610da6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f4c324f75747075744f7261636c653a2063616e6e6f742064656c657465206f7560448201527f74707574732074686174206861766520616c7265616479206265656e2066696e60648201527f616c697a65640000000000000000000000000000000000000000000000000000608482015260a40161059d565b6000610db160035490565b90508160035581817f4ee37ac2c786ec85e87592d3c5c8a1dd66f8496dda3f125d9ea8ca5f657629b660405160405180910390a35050565b60075473ffffffffffffffffffffffffffffffffffffffff163314610eb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f4c324f75747075744f7261636c653a206f6e6c79207468652070726f706f736560448201527f7220616464726573732063616e2070726f706f7365206e6577206f757470757460648201527f7300000000000000000000000000000000000000000000000000000000000000608482015260a40161059d565b610ebe611346565b8314610f72576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604860248201527f4c324f75747075744f7261636c653a20626c6f636b206e756d626572206d757360448201527f7420626520657175616c20746f206e65787420657870656374656420626c6f6360648201527f6b206e756d626572000000000000000000000000000000000000000000000000608482015260a40161059d565b42610f7c84611316565b10611009576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324f75747075744f7261636c653a2063616e6e6f742070726f706f7365204c60448201527f32206f757470757420696e207468652066757475726500000000000000000000606482015260840161059d565b83611096576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f4c324f75747075744f7261636c653a204c32206f75747075742070726f706f7360448201527f616c2063616e6e6f7420626520746865207a65726f2068617368000000000000606482015260840161059d565b81156111525781814014611152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604960248201527f4c324f75747075744f7261636c653a20626c6f636b206861736820646f65732060448201527f6e6f74206d61746368207468652068617368206174207468652065787065637460648201527f6564206865696768740000000000000000000000000000000000000000000000608482015260a40161059d565b8261115c60035490565b857fa7aaf2512769da4e444e3de247be2564225c2e7a8f74cfe528e46e17d24868e24260405161118e91815260200190565b60405180910390a45050604080516060810182529283526fffffffffffffffffffffffffffffffff4281166020850190815292811691840191825260038054600181018255600091909152935160029094027fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b810194909455915190518216700100000000000000000000000000000000029116177fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85c90910155565b60408051606081018252600080825260208201819052918101919091526003828154811061127a5761127a611509565b600091825260209182902060408051606081018252600290930290910180548352600101546fffffffffffffffffffffffffffffffff8082169484019490945270010000000000000000000000000000000090049092169181019190915292915050565b604080516060810182526000808252602082018190529181019190915260036113068361093b565b8154811061127a5761127a611509565b60006005546001548361132991906114f2565b611333919061158b565b6002546113409190611538565b92915050565b60006004546113536108b6565b6109249190611538565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b803573ffffffffffffffffffffffffffffffffffffffff8116811461139d57600080fd5b919050565b600080600080600080600060e0888a0312156113bd57600080fd5b873596506020880135955060408801359450606088013593506113e260808901611379565b92506113f060a08901611379565b915060c0880135905092959891949750929550565b600060208083528351808285015260005b8181101561143257858101830151858201604001528201611416565b81811115611444576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561148a57600080fd5b5035919050565b600080600080608085870312156114a757600080fd5b5050823594602084013594506040840135936060013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611504576115046114c3565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000821982111561154b5761154b6114c3565b500190565b600082611586577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156115c3576115c36114c3565b50029056fea2646970667358221220edf501b5b7dcf4c5e19b983dda098fcc35eb5250ade1df49e11ac69ef4b6059564736f6c634300080f0033
Deployed Bytecode Sourcemap
611:13467:5:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5264:92;;;;;;;;;;-1:-1:-1;5338:11:5;;5264:92;;;160:25:12;;;148:2;133:18;5264:92:5;;;;;;;;3742:985;;;;;;;;;;-1:-1:-1;3742:985:5;;;;;:::i;:::-;;:::i;:::-;;13254:174;;;;;;;;;;;;;:::i;4953:105::-;;;;;;;;;;-1:-1:-1;5033:18:5;;4953:105;;1426:25;;;;;;;;;;-1:-1:-1;1426:25:5;;;;;;;;;;;1182:42:12;1170:55;;;1152:74;;1140:2;1125:18;1426:25:5;1006:226:12;2598:40:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;12650:105::-;;;;;;;;;;;;;:::i;12891:97::-;;;;;;;;;;-1:-1:-1;12965:9:5;:16;12891:97;;5580:88;;;;;;;;;;-1:-1:-1;5651:10:5;;;;5580:88;;743:34;;;;;;;;;;;;;;;;11011:896;;;;;;;;;;-1:-1:-1;11011:896:5;;;;;:::i;:::-;;:::i;863:32::-;;;;;;;;;;;;;;;;6731:975;;;;;;;;;;-1:-1:-1;6731:975:5;;;;;:::i;:::-;;:::i;1285:26::-;;;;;;;;;;;;;;;;8300:1981;;;;;;:::i;:::-;;:::i;10485:146::-;;;;;;;;;;-1:-1:-1;10485:146:5;;;;;:::i;:::-;;:::i;:::-;;;;2701:13:12;;2683:32;;2762:4;2750:17;;;2744:24;2787:34;2859:21;;;2837:20;;;2830:51;;;;2929:17;;;2923:24;2919:33;;;2897:20;;;2890:63;2671:2;2656:18;10485:146:5;2473:486:12;1564:23:5;;;;;;;;;;-1:-1:-1;1564:23:5;;;;;;;;5886:84;;;;;;;;;;-1:-1:-1;5955:8:5;;;;5886:84;;1728:40;;;;;;;;;;;;;;;;12270:174;;;;;;;;;;-1:-1:-1;12270:174:5;;;;;:::i;:::-;;:::i;13896:180::-;;;;;;;;;;-1:-1:-1;13896:180:5;;;;;:::i;:::-;;:::i;13566:121::-;;;;;;;;;;;;;:::i;1114:33::-;;;;;;;;;;;;;;;;6221:120;;;;;;;;;;-1:-1:-1;6309:25:5;;6221:120;;3742:985;3100:19:0;3123:13;;;;;;3122:14;;3168:34;;;;-1:-1:-1;3186:12:0;;3201:1;3186:12;;;;:16;3168:34;3167:97;;;-1:-1:-1;3236:4:0;1465:19:1;:23;;;3208:55:0;;-1:-1:-1;3246:12:0;;;;;:17;3208:55;3146:190;;;;;;;3166:2:12;3146:190:0;;;3148:21:12;3205:2;3185:18;;;3178:30;3244:34;3224:18;;;3217:62;3315:16;3295:18;;;3288:44;3349:19;;3146:190:0;;;;;;;;;3346:12;:16;;;;3361:1;3346:16;;;3372:65;;;;3406:13;:20;;;;;;;;3372:65;4088:1:5::1;4066:19;:23;4058:94;;;::::0;::::1;::::0;;3581:2:12;4058:94:5::1;::::0;::::1;3563:21:12::0;3620:2;3600:18;;;3593:30;3659:34;3639:18;;;3632:62;3730:28;3710:18;;;3703:56;3776:19;;4058:94:5::1;3379:422:12::0;4058:94:5::1;4185:1;4170:12;:16;4162:81;;;::::0;::::1;::::0;;4008:2:12;4162:81:5::1;::::0;::::1;3990:21:12::0;4047:2;4027:18;;;4020:30;4086:34;4066:18;;;4059:62;4157:22;4137:18;;;4130:50;4197:19;;4162:81:5::1;3806:416:12::0;4162:81:5::1;4296:15;4274:18;:37;;4253:152;;;::::0;::::1;::::0;;4429:2:12;4253:152:5::1;::::0;::::1;4411:21:12::0;4468:2;4448:18;;;4441:30;;;4507:34;4487:18;;;4480:62;4578:34;4558:18;;;4551:62;4650:6;4629:19;;;4622:35;4674:19;;4253:152:5::1;4227:472:12::0;4253:152:5::1;4416:18;:40:::0;;;4466:11:::1;:26:::0;;;4502:19:::1;:42:::0;;;4554:17:::1;:38:::0;;;4602:8:::1;:20:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;4632:10:::1;:24:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;4666:25:::1;:54:::0;;;3457:99:0;;;;3507:5;3491:21;;;;;;3531:14;;-1:-1:-1;4856:36:12;;3531:14:0;;4844:2:12;4829:18;3531:14:0;;;;;;;3457:99;3090:472;3742:985:5;;;;;;;:::o;13254:174::-;13330:9;:16;13304:7;;13330:21;:91;;13376:9;13386:16;;:20;;13405:1;;13386:20;:::i;:::-;13376:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:45;;;;;;;;;13254:174;-1:-1:-1;13254:174:5:o;13330:91::-;13354:19;;13330:91;13323:98;;13254:174;:::o;12650:105::-;12728:9;:16;12702:7;;12728:20;;12747:1;;12728:20;:::i;11011:896::-;11087:7;11226:19;:17;:19::i;:::-;11208:14;:37;;11187:156;;;;;;;5613:2:12;11187:156:5;;;5595:21:12;5652:2;5632:18;;;5625:30;5691:34;5671:18;;;5664:62;5762:34;5742:18;;;5735:62;5834:10;5813:19;;;5806:39;5862:19;;11187:156:5;5411:476:12;11187:156:5;11421:9;:16;11413:103;;;;;;;6094:2:12;11413:103:5;;;6076:21:12;6133:2;6113:18;;;6106:30;6172:34;6152:18;;;6145:62;6243:34;6223:18;;;6216:62;6315:8;6294:19;;;6287:37;6341:19;;11413:103:5;5892:474:12;11413:103:5;11631:9;:16;11594:10;;11657:224;11669:2;11664;:7;11657:224;;;11687:11;11713:1;11702:7;11707:2;11702;:7;:::i;:::-;11701:13;;;;:::i;:::-;11687:27;;11763:14;11732:9;11742:3;11732:14;;;;;;;;:::i;:::-;;;;;;;;;;;;;;:28;;;;;;;;:45;11728:143;;;11802:7;:3;11808:1;11802:7;:::i;:::-;11797:12;;11728:143;;;11853:3;11848:8;;11728:143;11673:208;11657:224;;;-1:-1:-1;11898:2:5;11011:896;-1:-1:-1;;11011:896:5:o;6731:975::-;6821:10;;;;6807;:24;6799:99;;;;;;;6985:2:12;6799:99:5;;;6967:21:12;7024:2;7004:18;;;6997:30;7063:34;7043:18;;;7036:62;7134:32;7114:18;;;7107:60;7184:19;;6799:99:5;6783:426:12;6799:99:5;7016:9;:16;6999:33;;6978:135;;;;;;;7416:2:12;6978:135:5;;;7398:21:12;7455:2;7435:18;;;7428:30;7494:34;7474:18;;;7467:62;7565:34;7545:18;;;7538:62;7637:5;7616:19;;;7609:34;7660:19;;6978:135:5;7214:471:12;6978:135:5;7280:25;;7242:9;7252:14;7242:25;;;;;;;;:::i;:::-;;;;;;;;;:35;:25;;;;;:35;;7224:53;;7242:35;;7224:15;:53;:::i;:::-;:81;7203:198;;;;;;;7892:2:12;7203:198:5;;;7874:21:12;7931:2;7911:18;;;7904:30;7970:34;7950:18;;;7943:62;8041:34;8021:18;;;8014:62;8113:8;8092:19;;;8085:37;8139:19;;7203:198:5;7690:474:12;7203:198:5;7412:29;7444:17;12965:9;:16;;12891:97;7444:17;7412:49;;7606:14;7590;7583:38;7684:14;7661:21;7646:53;;;;;;;;;;6789:917;6731:975;:::o;8300:1981::-;8523:8;;;;8509:10;:22;8501:100;;;;;;;8371:2:12;8501:100:5;;;8353:21:12;8410:2;8390:18;;;8383:30;8449:34;8429:18;;;8422:62;8520:34;8500:18;;;8493:62;8592:3;8571:19;;;8564:32;8613:19;;8501:100:5;8169:469:12;8501:100:5;8651:17;:15;:17::i;:::-;8633:14;:35;8612:154;;;;;;;8845:2:12;8612:154:5;;;8827:21:12;8884:2;8864:18;;;8857:30;8923:34;8903:18;;;8896:62;8994:34;8974:18;;;8967:62;9066:10;9045:19;;;9038:39;9094:19;;8612:154:5;8643:476:12;8612:154:5;8835:15;8798:34;8817:14;8798:18;:34::i;:::-;:52;8777:153;;;;;;;9326:2:12;8777:153:5;;;9308:21:12;9365:2;9345:18;;;9338:30;9404:34;9384:18;;;9377:62;9475:24;9455:18;;;9448:52;9517:19;;8777:153:5;9124:418:12;8777:153:5;8949:11;8941:96;;;;;;;9749:2:12;8941:96:5;;;9731:21:12;9788:2;9768:18;;;9761:30;9827:34;9807:18;;;9800:62;9898:28;9878:18;;;9871:56;9944:19;;8941:96:5;9547:422:12;8941:96:5;9052:26;;9048:897;;9815:12;9796:14;9786:25;:41;9761:173;;;;;;;10176:2:12;9761:173:5;;;10158:21:12;10215:2;10195:18;;;10188:30;10254:34;10234:18;;;10227:62;10325:34;10305:18;;;10298:62;10397:11;10376:19;;;10369:40;10426:19;;9761:173:5;9974:477:12;9761:173:5;10007:14;9988:17;12965:9;:16;;12891:97;9988:17;9975:11;9960:79;10023:15;9960:79;;;;160:25:12;;148:2;133:18;;14:177;9960:79:5;;;;;;;;-1:-1:-1;;10078:186:5;;;;;;;;;;;;10177:15;10078:186;;;;;;;;;;;;;;;;;10050:9;:224;;;;;;;-1:-1:-1;10050:224:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8300:1981::o;10485:146::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;10599:9:5;10609:14;10599:25;;;;;;;;:::i;:::-;;;;;;;;;;10592:32;;;;;;;;10599:25;;;;;;;10592:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10485:146;-1:-1:-1;;10485:146:5:o;12270:174::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;12389:9:5;12399:37;12421:14;12399:21;:37::i;:::-;12389:48;;;;;;;;:::i;13896:180::-;13969:7;14057:11;;14034:19;;14017:14;:36;;;;:::i;:::-;14016:52;;;;:::i;:::-;13995:17;;:74;;;;:::i;:::-;13988:81;13896:180;-1:-1:-1;;13896:180:5:o;13566:121::-;13614:7;13662:18;;13640:19;:17;:19::i;:::-;:40;;;;:::i;1175:320:1:-;1465:19;;;:23;;;1175:320::o;196:196:12:-;264:20;;324:42;313:54;;303:65;;293:93;;382:1;379;372:12;293:93;196:196;;;:::o;397:604::-;510:6;518;526;534;542;550;558;611:3;599:9;590:7;586:23;582:33;579:53;;;628:1;625;618:12;579:53;664:9;651:23;641:33;;721:2;710:9;706:18;693:32;683:42;;772:2;761:9;757:18;744:32;734:42;;823:2;812:9;808:18;795:32;785:42;;846:39;880:3;869:9;865:19;846:39;:::i;:::-;836:49;;904:39;938:3;927:9;923:19;904:39;:::i;:::-;894:49;;990:3;979:9;975:19;962:33;952:43;;397:604;;;;;;;;;;:::o;1237:656::-;1349:4;1378:2;1407;1396:9;1389:21;1439:6;1433:13;1482:6;1477:2;1466:9;1462:18;1455:34;1507:1;1517:140;1531:6;1528:1;1525:13;1517:140;;;1626:14;;;1622:23;;1616:30;1592:17;;;1611:2;1588:26;1581:66;1546:10;;1517:140;;;1675:6;1672:1;1669:13;1666:91;;;1745:1;1740:2;1731:6;1720:9;1716:22;1712:31;1705:42;1666:91;-1:-1:-1;1809:2:12;1797:15;1814:66;1793:88;1778:104;;;;1884:2;1774:113;;1237:656;-1:-1:-1;;;1237:656:12:o;1898:180::-;1957:6;2010:2;1998:9;1989:7;1985:23;1981:32;1978:52;;;2026:1;2023;2016:12;1978:52;-1:-1:-1;2049:23:12;;1898:180;-1:-1:-1;1898:180:12:o;2083:385::-;2169:6;2177;2185;2193;2246:3;2234:9;2225:7;2221:23;2217:33;2214:53;;;2263:1;2260;2253:12;2214:53;-1:-1:-1;;2286:23:12;;;2356:2;2341:18;;2328:32;;-1:-1:-1;2407:2:12;2392:18;;2379:32;;2458:2;2443:18;2430:32;;-1:-1:-1;2083:385:12;-1:-1:-1;2083:385:12:o;4903:184::-;4955:77;4952:1;4945:88;5052:4;5049:1;5042:15;5076:4;5073:1;5066:15;5092:125;5132:4;5160:1;5157;5154:8;5151:34;;;5165:18;;:::i;:::-;-1:-1:-1;5202:9:12;;5092:125::o;5222:184::-;5274:77;5271:1;5264:88;5371:4;5368:1;5361:15;5395:4;5392:1;5385:15;6371:128;6411:3;6442:1;6438:6;6435:1;6432:13;6429:39;;;6448:18;;:::i;:::-;-1:-1:-1;6484:9:12;;6371:128::o;6504:274::-;6544:1;6570;6560:189;;6605:77;6602:1;6595:88;6706:4;6703:1;6696:15;6734:4;6731:1;6724:15;6560:189;-1:-1:-1;6763:9:12;;6504:274::o;10456:228::-;10496:7;10622:1;10554:66;10550:74;10547:1;10544:81;10539:1;10532:9;10525:17;10521:105;10518:131;;;10629:18;;:::i;:::-;-1:-1:-1;10669:9:12;;10456:228::o
Swarm Source
ipfs://edf501b5b7dcf4c5e19b983dda098fcc35eb5250ade1df49e11ac69ef4b60595
Loading...
Loading
[ Download: CSV Export ]
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.