Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
19386662 | 264 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
SystemConfig
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 999999 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { ISemver } from "src/universal/ISemver.sol"; import { ResourceMetering } from "src/L1/ResourceMetering.sol"; import { Storage } from "src/libraries/Storage.sol"; import { Constants } from "src/libraries/Constants.sol"; /// @title SystemConfig /// @notice The SystemConfig contract is used to manage configuration of an Optimism network. /// All configuration is stored on L1 and picked up by L2 as part of the derviation of /// the L2 chain. contract SystemConfig is OwnableUpgradeable, ISemver { /// @notice Enum representing different types of updates. /// @custom:value BATCHER Represents an update to the batcher hash. /// @custom:value GAS_CONFIG Represents an update to txn fee config on L2. /// @custom:value GAS_LIMIT Represents an update to gas limit on L2. /// @custom:value UNSAFE_BLOCK_SIGNER Represents an update to the signer key for unsafe /// block distrubution. enum UpdateType { BATCHER, GAS_CONFIG, GAS_LIMIT, UNSAFE_BLOCK_SIGNER } /// @notice Struct representing the addresses of L1 system contracts. These should be the /// proxies and are network specific. struct Addresses { address l1CrossDomainMessenger; address l1ERC721Bridge; address l1StandardBridge; address l2OutputOracle; address optimismPortal; address optimismMintableERC20Factory; } /// @notice Version identifier, used for upgrades. uint256 public constant VERSION = 0; /// @notice Storage slot that the unsafe block signer is stored at. /// Storing it at this deterministic storage slot allows for decoupling the storage /// layout from the way that `solc` lays out storage. The `op-node` uses a storage /// proof to fetch this value. /// @dev NOTE: this value will be migrated to another storage slot in a future version. /// User input should not be placed in storage in this contract until this migration /// happens. It is unlikely that keccak second preimage resistance will be broken, /// but it is better to be safe than sorry. bytes32 public constant UNSAFE_BLOCK_SIGNER_SLOT = keccak256("systemconfig.unsafeblocksigner"); /// @notice Storage slot that the L1CrossDomainMessenger address is stored at. bytes32 public constant L1_CROSS_DOMAIN_MESSENGER_SLOT = bytes32(uint256(keccak256("systemconfig.l1crossdomainmessenger")) - 1); /// @notice Storage slot that the L1ERC721Bridge address is stored at. bytes32 public constant L1_ERC_721_BRIDGE_SLOT = bytes32(uint256(keccak256("systemconfig.l1erc721bridge")) - 1); /// @notice Storage slot that the L1StandardBridge address is stored at. bytes32 public constant L1_STANDARD_BRIDGE_SLOT = bytes32(uint256(keccak256("systemconfig.l1standardbridge")) - 1); /// @notice Storage slot that the L2OutputOracle address is stored at. bytes32 public constant L2_OUTPUT_ORACLE_SLOT = bytes32(uint256(keccak256("systemconfig.l2outputoracle")) - 1); /// @notice Storage slot that the OptimismPortal address is stored at. bytes32 public constant OPTIMISM_PORTAL_SLOT = bytes32(uint256(keccak256("systemconfig.optimismportal")) - 1); /// @notice Storage slot that the OptimismMintableERC20Factory address is stored at. bytes32 public constant OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT = bytes32(uint256(keccak256("systemconfig.optimismmintableerc20factory")) - 1); /// @notice Storage slot that the batch inbox address is stored at. bytes32 public constant BATCH_INBOX_SLOT = bytes32(uint256(keccak256("systemconfig.batchinbox")) - 1); /// @notice Storage slot for block at which the op-node can start searching for logs from. bytes32 public constant START_BLOCK_SLOT = bytes32(uint256(keccak256("systemconfig.startBlock")) - 1); /// @notice Fixed L2 gas overhead. Used as part of the L2 fee calculation. uint256 public overhead; /// @notice Dynamic L2 gas overhead. Used as part of the L2 fee calculation. uint256 public scalar; /// @notice Identifier for the batcher. /// For version 1 of this configuration, this is represented as an address left-padded /// with zeros to 32 bytes. bytes32 public batcherHash; /// @notice L2 block gas limit. uint64 public gasLimit; /// @notice The configuration for the deposit fee market. /// Used by the OptimismPortal to meter the cost of buying L2 gas on L1. /// Set as internal with a getter so that the struct is returned instead of a tuple. ResourceMetering.ResourceConfig internal _resourceConfig; /// @notice Emitted when configuration is updated. /// @param version SystemConfig version. /// @param updateType Type of update. /// @param data Encoded update data. event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); /// @notice Semantic version. /// @custom:semver 1.12.0 string public constant version = "1.12.0"; /// @notice Constructs the SystemConfig contract. Cannot set /// the owner to `address(0)` due to the Ownable contract's /// implementation, so set it to `address(0xdEaD)` /// @dev START_BLOCK_SLOT is set to type(uint256).max here so that it will be a dead value /// in the singleton and is skipped by initialize when setting the start block. constructor() { Storage.setUint(START_BLOCK_SLOT, type(uint256).max); initialize({ _owner: address(0xdEaD), _overhead: 0, _scalar: 0, _batcherHash: bytes32(0), _gasLimit: 1, _unsafeBlockSigner: address(0), _config: ResourceMetering.ResourceConfig({ maxResourceLimit: 1, elasticityMultiplier: 1, baseFeeMaxChangeDenominator: 2, minimumBaseFee: 0, systemTxMaxGas: 0, maximumBaseFee: 0 }), _batchInbox: address(0), _addresses: SystemConfig.Addresses({ l1CrossDomainMessenger: address(0), l1ERC721Bridge: address(0), l1StandardBridge: address(0), l2OutputOracle: address(0), optimismPortal: address(0), optimismMintableERC20Factory: address(0) }) }); } /// @notice Initializer. /// The resource config must be set before the require check. /// @param _owner Initial owner of the contract. /// @param _overhead Initial overhead value. /// @param _scalar Initial scalar value. /// @param _batcherHash Initial batcher hash. /// @param _gasLimit Initial gas limit. /// @param _unsafeBlockSigner Initial unsafe block signer address. /// @param _config Initial ResourceConfig. /// @param _batchInbox Batch inbox address. An identifier for the op-node to find /// canonical data. /// @param _addresses Set of L1 contract addresses. These should be the proxies. function initialize( address _owner, uint256 _overhead, uint256 _scalar, bytes32 _batcherHash, uint64 _gasLimit, address _unsafeBlockSigner, ResourceMetering.ResourceConfig memory _config, address _batchInbox, SystemConfig.Addresses memory _addresses ) public initializer { __Ownable_init(); transferOwnership(_owner); // These are set in ascending order of their UpdateTypes. _setBatcherHash(_batcherHash); _setGasConfig({ _overhead: _overhead, _scalar: _scalar }); _setGasLimit(_gasLimit); Storage.setAddress(UNSAFE_BLOCK_SIGNER_SLOT, _unsafeBlockSigner); Storage.setAddress(BATCH_INBOX_SLOT, _batchInbox); Storage.setAddress(L1_CROSS_DOMAIN_MESSENGER_SLOT, _addresses.l1CrossDomainMessenger); Storage.setAddress(L1_ERC_721_BRIDGE_SLOT, _addresses.l1ERC721Bridge); Storage.setAddress(L1_STANDARD_BRIDGE_SLOT, _addresses.l1StandardBridge); Storage.setAddress(L2_OUTPUT_ORACLE_SLOT, _addresses.l2OutputOracle); Storage.setAddress(OPTIMISM_PORTAL_SLOT, _addresses.optimismPortal); Storage.setAddress(OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT, _addresses.optimismMintableERC20Factory); _setStartBlock(); _setResourceConfig(_config); require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low"); } /// @notice Returns the minimum L2 gas limit that can be safely set for the system to /// operate. The L2 gas limit must be larger than or equal to the amount of /// gas that is allocated for deposits per block plus the amount of gas that /// is allocated for the system transaction. /// This function is used to determine if changes to parameters are safe. /// @return uint64 Minimum gas limit. function minimumGasLimit() public view returns (uint64) { return uint64(_resourceConfig.maxResourceLimit) + uint64(_resourceConfig.systemTxMaxGas); } /// @notice High level getter for the unsafe block signer address. /// Unsafe blocks can be propagated across the p2p network if they are signed by the /// key corresponding to this address. /// @return addr_ Address of the unsafe block signer. // solhint-disable-next-line ordering function unsafeBlockSigner() public view returns (address addr_) { addr_ = Storage.getAddress(UNSAFE_BLOCK_SIGNER_SLOT); } /// @notice Getter for the L1CrossDomainMessenger address. function l1CrossDomainMessenger() external view returns (address addr_) { addr_ = Storage.getAddress(L1_CROSS_DOMAIN_MESSENGER_SLOT); } /// @notice Getter for the L1ERC721Bridge address. function l1ERC721Bridge() external view returns (address addr_) { addr_ = Storage.getAddress(L1_ERC_721_BRIDGE_SLOT); } /// @notice Getter for the L1StandardBridge address. function l1StandardBridge() external view returns (address addr_) { addr_ = Storage.getAddress(L1_STANDARD_BRIDGE_SLOT); } /// @notice Getter for the L2OutputOracle address. function l2OutputOracle() external view returns (address addr_) { addr_ = Storage.getAddress(L2_OUTPUT_ORACLE_SLOT); } /// @notice Getter for the OptimismPortal address. function optimismPortal() external view returns (address addr_) { addr_ = Storage.getAddress(OPTIMISM_PORTAL_SLOT); } /// @notice Getter for the OptimismMintableERC20Factory address. function optimismMintableERC20Factory() external view returns (address addr_) { addr_ = Storage.getAddress(OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT); } /// @notice Getter for the BatchInbox address. function batchInbox() external view returns (address addr_) { addr_ = Storage.getAddress(BATCH_INBOX_SLOT); } /// @notice Getter for the StartBlock number. function startBlock() external view returns (uint256 startBlock_) { startBlock_ = Storage.getUint(START_BLOCK_SLOT); } /// @notice Updates the unsafe block signer address. Can only be called by the owner. /// @param _unsafeBlockSigner New unsafe block signer address. function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner { _setUnsafeBlockSigner(_unsafeBlockSigner); } /// @notice Updates the unsafe block signer address. /// @param _unsafeBlockSigner New unsafe block signer address. function _setUnsafeBlockSigner(address _unsafeBlockSigner) internal { Storage.setAddress(UNSAFE_BLOCK_SIGNER_SLOT, _unsafeBlockSigner); bytes memory data = abi.encode(_unsafeBlockSigner); emit ConfigUpdate(VERSION, UpdateType.UNSAFE_BLOCK_SIGNER, data); } /// @notice Updates the batcher hash. Can only be called by the owner. /// @param _batcherHash New batcher hash. function setBatcherHash(bytes32 _batcherHash) external onlyOwner { _setBatcherHash(_batcherHash); } /// @notice Internal function for updating the batcher hash. /// @param _batcherHash New batcher hash. function _setBatcherHash(bytes32 _batcherHash) internal { batcherHash = _batcherHash; bytes memory data = abi.encode(_batcherHash); emit ConfigUpdate(VERSION, UpdateType.BATCHER, data); } /// @notice Updates gas config. Can only be called by the owner. /// @param _overhead New overhead value. /// @param _scalar New scalar value. function setGasConfig(uint256 _overhead, uint256 _scalar) external onlyOwner { _setGasConfig(_overhead, _scalar); } /// @notice Internal function for updating the gas config. /// @param _overhead New overhead value. /// @param _scalar New scalar value. function _setGasConfig(uint256 _overhead, uint256 _scalar) internal { overhead = _overhead; scalar = _scalar; bytes memory data = abi.encode(_overhead, _scalar); emit ConfigUpdate(VERSION, UpdateType.GAS_CONFIG, data); } /// @notice Updates the L2 gas limit. Can only be called by the owner. /// @param _gasLimit New gas limit. function setGasLimit(uint64 _gasLimit) external onlyOwner { _setGasLimit(_gasLimit); } /// @notice Internal function for updating the L2 gas limit. /// @param _gasLimit New gas limit. function _setGasLimit(uint64 _gasLimit) internal { require(_gasLimit >= minimumGasLimit(), "SystemConfig: gas limit too low"); gasLimit = _gasLimit; bytes memory data = abi.encode(_gasLimit); emit ConfigUpdate(VERSION, UpdateType.GAS_LIMIT, data); } /// @notice Sets the start block in a backwards compatible way. Proxies /// that were initialized before the startBlock existed in storage /// can have their start block set by a user provided override. /// A start block of 0 indicates that there is no override and the /// start block will be set by `block.number`. /// @dev This logic is used to patch legacy deployments with new storage values. /// Use the override if it is provided as a non zero value and the value /// has not already been set in storage. Use `block.number` if the value /// has already been set in storage function _setStartBlock() internal { if (Storage.getUint(START_BLOCK_SLOT) == 0) { Storage.setUint(START_BLOCK_SLOT, block.number); } } /// @notice A getter for the resource config. /// Ensures that the struct is returned instead of a tuple. /// @return ResourceConfig function resourceConfig() external view returns (ResourceMetering.ResourceConfig memory) { return _resourceConfig; } /// @notice An external setter for the resource config. /// In the future, this method may emit an event that the `op-node` picks up /// for when the resource config is changed. /// @param _config The new resource config values. function setResourceConfig(ResourceMetering.ResourceConfig memory _config) external onlyOwner { _setResourceConfig(_config); } /// @notice An internal setter for the resource config. /// Ensures that the config is sane before storing it by checking for invariants. /// @param _config The new resource config. function _setResourceConfig(ResourceMetering.ResourceConfig memory _config) internal { // Min base fee must be less than or equal to max base fee. require( _config.minimumBaseFee <= _config.maximumBaseFee, "SystemConfig: min base fee must be less than max base" ); // Base fee change denominator must be greater than 1. require(_config.baseFeeMaxChangeDenominator > 1, "SystemConfig: denominator must be larger than 1"); // Max resource limit plus system tx gas must be less than or equal to the L2 gas limit. // The gas limit must be increased before these values can be increased. require(_config.maxResourceLimit + _config.systemTxMaxGas <= gasLimit, "SystemConfig: gas limit too low"); // Elasticity multiplier must be greater than 0. require(_config.elasticityMultiplier > 0, "SystemConfig: elasticity multiplier cannot be 0"); // No precision loss when computing target resource limit. require( ((_config.maxResourceLimit / _config.elasticityMultiplier) * _config.elasticityMultiplier) == _config.maxResourceLimit, "SystemConfig: precision loss with target resource limit" ); _resourceConfig = _config; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT 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.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 pragma solidity ^0.8.0; /// @title Storage /// @notice Storage handles reading and writing to arbitary storage locations library Storage { /// @notice Returns an address stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getAddress(bytes32 _slot) internal view returns (address addr_) { assembly { addr_ := sload(_slot) } } /// @notice Stores an address in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _address The protocol version to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting addresses /// in arbitrary storage slots. function setAddress(bytes32 _slot, address _address) internal { assembly { sstore(_slot, _address) } } /// @notice Returns a uint256 stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getUint(bytes32 _slot) internal view returns (uint256 value_) { assembly { value_ := sload(_slot) } } /// @notice Stores a value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _value The protocol version to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setUint(bytes32 _slot, uint256 _value) internal { assembly { sstore(_slot, _value) } } /// @notice Returns a bytes32 stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getBytes32(bytes32 _slot) internal view returns (bytes32 value_) { assembly { value_ := sload(_slot) } } /// @notice Stores a bytes32 value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _value The bytes32 value to store. /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setBytes32(bytes32 _slot, bytes32 _value) internal { assembly { sstore(_slot, _value) } } /// @notice Stores a bool value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the bool in. /// @param _value The bool value to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setBool(bytes32 _slot, bool _value) internal { assembly { sstore(_slot, _value) } } /// @notice Returns a bool stored in an arbitrary storage slot. /// @param _slot The storage slot to retrieve the bool from. function getBool(bytes32 _slot) internal view returns (bool value_) { assembly { value_ := sload(_slot) } } }
// 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 v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * 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) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `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 // 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 // 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.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [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 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 // 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 // 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": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@rari-capital/solmate/=lib/solmate/", "@cwia/=lib/clones-with-immutable-args/src/", "@lib-keccak/=lib/lib-keccak/contracts/lib/", "forge-std/=lib/forge-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "safe-contracts/=lib/safe-contracts/contracts/", "kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/", "solady/=lib/solady/src/", "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "lib-keccak/=lib/lib-keccak/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 999999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":true,"internalType":"enum SystemConfig.UpdateType","name":"updateType","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ConfigUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"BATCH_INBOX_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L1_CROSS_DOMAIN_MESSENGER_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L1_ERC_721_BRIDGE_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L1_STANDARD_BRIDGE_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"L2_OUTPUT_ORACLE_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTIMISM_PORTAL_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"START_BLOCK_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNSAFE_BLOCK_SIGNER_SLOT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batchInbox","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"batcherHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasLimit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_overhead","type":"uint256"},{"internalType":"uint256","name":"_scalar","type":"uint256"},{"internalType":"bytes32","name":"_batcherHash","type":"bytes32"},{"internalType":"uint64","name":"_gasLimit","type":"uint64"},{"internalType":"address","name":"_unsafeBlockSigner","type":"address"},{"components":[{"internalType":"uint32","name":"maxResourceLimit","type":"uint32"},{"internalType":"uint8","name":"elasticityMultiplier","type":"uint8"},{"internalType":"uint8","name":"baseFeeMaxChangeDenominator","type":"uint8"},{"internalType":"uint32","name":"minimumBaseFee","type":"uint32"},{"internalType":"uint32","name":"systemTxMaxGas","type":"uint32"},{"internalType":"uint128","name":"maximumBaseFee","type":"uint128"}],"internalType":"struct ResourceMetering.ResourceConfig","name":"_config","type":"tuple"},{"internalType":"address","name":"_batchInbox","type":"address"},{"components":[{"internalType":"address","name":"l1CrossDomainMessenger","type":"address"},{"internalType":"address","name":"l1ERC721Bridge","type":"address"},{"internalType":"address","name":"l1StandardBridge","type":"address"},{"internalType":"address","name":"l2OutputOracle","type":"address"},{"internalType":"address","name":"optimismPortal","type":"address"},{"internalType":"address","name":"optimismMintableERC20Factory","type":"address"}],"internalType":"struct SystemConfig.Addresses","name":"_addresses","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"l1CrossDomainMessenger","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l1ERC721Bridge","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l1StandardBridge","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2OutputOracle","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumGasLimit","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimismMintableERC20Factory","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"optimismPortal","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"overhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resourceConfig","outputs":[{"components":[{"internalType":"uint32","name":"maxResourceLimit","type":"uint32"},{"internalType":"uint8","name":"elasticityMultiplier","type":"uint8"},{"internalType":"uint8","name":"baseFeeMaxChangeDenominator","type":"uint8"},{"internalType":"uint32","name":"minimumBaseFee","type":"uint32"},{"internalType":"uint32","name":"systemTxMaxGas","type":"uint32"},{"internalType":"uint128","name":"maximumBaseFee","type":"uint128"}],"internalType":"struct ResourceMetering.ResourceConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scalar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_batcherHash","type":"bytes32"}],"name":"setBatcherHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_overhead","type":"uint256"},{"internalType":"uint256","name":"_scalar","type":"uint256"}],"name":"setGasConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"_gasLimit","type":"uint64"}],"name":"setGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"maxResourceLimit","type":"uint32"},{"internalType":"uint8","name":"elasticityMultiplier","type":"uint8"},{"internalType":"uint8","name":"baseFeeMaxChangeDenominator","type":"uint8"},{"internalType":"uint32","name":"minimumBaseFee","type":"uint32"},{"internalType":"uint32","name":"systemTxMaxGas","type":"uint32"},{"internalType":"uint128","name":"maximumBaseFee","type":"uint128"}],"internalType":"struct ResourceMetering.ResourceConfig","name":"_config","type":"tuple"}],"name":"setResourceConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_unsafeBlockSigner","type":"address"}],"name":"setUnsafeBlockSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"startBlock_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unsafeBlockSigner","outputs":[{"internalType":"address","name":"addr_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200004962000032600160008051602062002a4783398151915262000c39565b60001b600019620000c960201b62000e061760201c565b6040805160c080820183526001808352602080840182905260028486015260006060808601829052608080870183905260a08088018490528851968701895283875293860183905296850182905284018190529483018590528201849052620000c39361dead9390928392839290918391908290620000cd565b62000d5c565b9055565b600054610100900460ff1615808015620000ee5750600054600160ff909116105b806200011e57506200010b30620004df60201b62000e0a1760201c565b1580156200011e575060005460ff166001145b620001875760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015620001ab576000805461ff0019166101001790555b620001b5620004ee565b620001c08a62000556565b620001cb87620005d5565b620001d7898962000627565b620001e2866200068b565b620002197f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0886620000c960201b62000e061760201c565b6200025f6200024a60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc59862000c39565b60001b84620000c960201b62000e061760201c565b620002a96200029060017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce958063762000c39565b60001b8360000151620000c960201b62000e061760201c565b620002f3620002da60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a862000c39565b60001b8360200151620000c960201b62000e061760201c565b6200033d6200032460017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad637762000c39565b60001b8360400151620000c960201b62000e061760201c565b620003876200036e60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a687181662000c39565b60001b8360600151620000c960201b62000e061760201c565b620003d1620003b860017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad62000c39565b60001b8360800151620000c960201b62000e061760201c565b6200041b6200040260017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d62000c39565b60001b8360a00151620000c960201b62000e061760201c565b6200042562000728565b620004308462000799565b6200043a62000add565b6001600160401b0316866001600160401b031610156200048c5760405162461bcd60e51b815260206004820152601f6024820152600080516020620029e783398151915260448201526064016200017e565b8015620004d3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6001600160a01b03163b151590565b600054610100900460ff166200054a5760405162461bcd60e51b815260206004820152602b602482015260008051602062002a2783398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200017e565b6200055462000b0a565b565b6200056062000b71565b6001600160a01b038116620005c75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016200017e565b620005d28162000bcd565b50565b60678190556040805160208082018490528251808303909101815290820190915260005b600060008051602062002a07833981519152836040516200061b919062000c53565b60405180910390a35050565b60658290556066819055604080516020810184905290810182905260009060600160408051601f1981840301815291905290506001600060008051602062002a07833981519152836040516200067e919062000c53565b60405180910390a3505050565b6200069562000add565b6001600160401b0316816001600160401b03161015620006e75760405162461bcd60e51b815260206004820152601f6024820152600080516020620029e783398151915260448201526064016200017e565b606880546001600160401b0319166001600160401b0383169081179091556040805160208082019390935281518082039093018352810190526002620005f9565b6200075c62000748600160008051602062002a4783398151915262000c39565b60001b62000c1f60201b62000e261760201c565b60000362000554576200055462000784600160008051602062002a4783398151915262000c39565b60001b43620000c960201b62000e061760201c565b8060a001516001600160801b0316816060015163ffffffff161115620008285760405162461bcd60e51b815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d61782062617365000000000000000000000060648201526084016200017e565b6001816040015160ff1611620008995760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201526e65206c6172676572207468616e203160881b60648201526084016200017e565b606854608082015182516001600160401b0390921691620008bb919062000cab565b63ffffffff161115620009005760405162461bcd60e51b815260206004820152601f6024820152600080516020620029e783398151915260448201526064016200017e565b6000816020015160ff1611620009715760405162461bcd60e51b815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201526e06965722063616e6e6f74206265203608c1b60648201526084016200017e565b8051602082015163ffffffff82169160ff909116906200099390829062000cd6565b6200099f919062000d08565b63ffffffff161462000a1a5760405162461bcd60e51b815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d697400000000000000000060648201526084016200017e565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff96871664ffffffffff199095169490941764010000000060ff948516021764ffffffffff60281b191665010000000000939092169290920263ffffffff60301b19161766010000000000009185169190910217600160501b600160f01b0319166a01000000000000000000009390941692909202600160701b600160f01b03191692909217600160701b6001600160801b0390921691909102179055565b60695460009062000b059063ffffffff6a010000000000000000000082048116911662000d37565b905090565b600054610100900460ff1662000b665760405162461bcd60e51b815260206004820152602b602482015260008051602062002a2783398151915260448201526a6e697469616c697a696e6760a81b60648201526084016200017e565b620005543362000bcd565b6033546001600160a01b03163314620005545760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200017e565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b5490565b634e487b7160e01b600052601160045260246000fd5b60008282101562000c4e5762000c4e62000c23565b500390565b600060208083528351808285015260005b8181101562000c825785810183015185820160400152820162000c64565b8181111562000c95576000604083870101525b50601f01601f1916929092016040019392505050565b600063ffffffff80831681851680830382111562000ccd5762000ccd62000c23565b01949350505050565b600063ffffffff8084168062000cfc57634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b600063ffffffff8083168185168183048111821515161562000d2e5762000d2e62000c23565b02949350505050565b60006001600160401b0382811684821680830382111562000ccd5762000ccd62000c23565b611c7b8062000d6c6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c8063935f029e11610145578063dac6e63a116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610597578063fd32aa0f1461059f578063ffa1ad74146105a757600080fd5b8063f45e65d81461057a578063f68016b71461058357600080fd5b8063dac6e63a1461054e578063e0e2016d14610556578063e81b2c6d1461055e578063f2fde38b1461056757600080fd5b8063bc49ce5f11610114578063c71973f6116100f9578063c71973f6146103f4578063c9b26f6114610407578063cc731b021461041a57600080fd5b8063bc49ce5f146103e4578063c4e8ddfa146103ec57600080fd5b8063935f029e146103ae5780639b7d7f0a146103c1578063a7119869146103c9578063b40a817c146103d157600080fd5b806348cd4cb1116101d857806354fd4d50116101a757806361d157681161018c57806361d1576814610380578063715018a6146103885780638da5cb5b1461039057600080fd5b806354fd4d501461032f5780635d73369c1461037857600080fd5b806348cd4cb1146102d75780634add321d146102df5780634d9f1559146103005780634f16540b1461030857600080fd5b80630c18c162116102145780630c18c162146102ab57806318d13918146102b457806319f5cea8146102c75780631fd19ee1146102cf57600080fd5b806306c9265714610246578063078f29cf146102615780630a49cb031461028e5780630bbb796814610296575b600080fd5b61024e6105af565b6040519081526020015b60405180910390f35b6102696105dd565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610258565b610269610616565b6102a96102a4366004611928565b610646565b005b61024e60655481565b6102a96102c2366004611a55565b610a44565b61024e610a58565b610269610a83565b61024e610aad565b6102e7610add565b60405167ffffffffffffffff9091168152602001610258565b610269610b03565b61024e7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61036b6040518060400160405280600681526020017f312e31322e30000000000000000000000000000000000000000000000000000081525081565b6040516102589190611ae2565b61024e610b33565b61024e610b5e565b6102a9610b89565b60335473ffffffffffffffffffffffffffffffffffffffff16610269565b6102a96103bc366004611af5565b610b9d565b610269610bb3565b610269610be3565b6102a96103df366004611b17565b610c13565b61024e610c24565b610269610c4f565b6102a9610402366004611b32565b610c7f565b6102a9610415366004611b4e565b610c90565b6104de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102589190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b610269610ca1565b61024e610cd1565b61024e60675481565b6102a9610575366004611a55565b610cfc565b61024e60665481565b6068546102e79067ffffffffffffffff1681565b61024e610db0565b61024e610ddb565b61024e600081565b6105da60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b81565b600061061161060d60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b5490565b905090565b600061061161060d60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b600054610100900460ff16158080156106665750600054600160ff909116105b806106805750303b158015610680575060005460ff166001145b610711576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561076f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610777610e2a565b6107808a610cfc565b61078987610ec9565b6107938989610f2a565b61079c86610fbb565b6107c57f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b6107f86107f360017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b849055565b61082c61082660017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b83519055565b61086361085a60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60208401519055565b61089a61089160017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b60408401519055565b6108d16108c860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b60608401519055565b6109086108ff60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b60808401519055565b61093f61093660017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b60a08401519055565b610947611099565b61095084611101565b610958610add565b67ffffffffffffffff168667ffffffffffffffff1610156109d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b8015610a3857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b610a4c611575565b610a55816115f6565b50565b6105da60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60006106117f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b600061061161060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b6069546000906106119063ffffffff6a0100000000000000000000820481169116611bad565b600061061161060d60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b6105da60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b6105da60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b610b91611575565b610b9b600061167a565b565b610ba5611575565b610baf8282610f2a565b5050565b600061061161060d60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b600061061161060d60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b610c1b611575565b610a5581610fbb565b6105da60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b600061061161060d60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b610c87611575565b610a5581611101565b610c98611575565b610a5581610ec9565b600061061161060d60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b6105da60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b610d04611575565b73ffffffffffffffffffffffffffffffffffffffff8116610da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610708565b610a558161167a565b6105da60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b6105da60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b5490565b600054610100900460ff16610ec1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b6116f1565b60678190556040805160208082018490528251808303909101815290820190915260005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610f1e9190611ae2565b60405180910390a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae9190611ae2565b60405180910390a3505050565b610fc3610add565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610eed565b6110c761060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b600003610b9b57610b9b6110fc60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b439055565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff1611156111b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610708565b6001816040015160ff1611611248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610708565b6068546080820151825167ffffffffffffffff909216916112699190611bd9565b63ffffffff1611156112d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b6000816020015160ff161161136e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610708565b8051602082015163ffffffff82169160ff9091169061138e908290611bf8565b6113989190611c42565b63ffffffff161461142b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610708565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610708565b61161f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290506003610eed565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b3361167a565b803573ffffffffffffffffffffffffffffffffffffffff811681146117b557600080fd5b919050565b803567ffffffffffffffff811681146117b557600080fd5b60405160c0810167ffffffffffffffff8111828210171561181c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff811681146117b557600080fd5b803560ff811681146117b557600080fd5b600060c0828403121561185957600080fd5b60405160c0810181811067ffffffffffffffff821117156118a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806118b283611822565b81526118c060208401611836565b60208201526118d160408401611836565b60408201526118e260608401611822565b60608201526118f360808401611822565b608082015260a08301356fffffffffffffffffffffffffffffffff8116811461191b57600080fd5b60a0919091015292915050565b6000806000806000806000806000898b0361026081121561194857600080fd5b6119518b611791565b995060208b0135985060408b0135975060608b0135965061197460808c016117ba565b955061198260a08c01611791565b94506119918c60c08d01611847565b93506119a06101808c01611791565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe60820112156119d257600080fd5b506119db6117d2565b6119e86101a08c01611791565b81526119f76101c08c01611791565b6020820152611a096101e08c01611791565b6040820152611a1b6102008c01611791565b6060820152611a2d6102208c01611791565b6080820152611a3f6102408c01611791565b60a0820152809150509295985092959850929598565b600060208284031215611a6757600080fd5b611a7082611791565b9392505050565b6000815180845260005b81811015611a9d57602081850181015186830182015201611a81565b81811115611aaf576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611a706020830184611a77565b60008060408385031215611b0857600080fd5b50508035926020909101359150565b600060208284031215611b2957600080fd5b611a70826117ba565b600060c08284031215611b4457600080fd5b611a708383611847565b600060208284031215611b6057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611ba857611ba8611b67565b500390565b600067ffffffffffffffff808316818516808303821115611bd057611bd0611b67565b01949350505050565b600063ffffffff808316818516808303821115611bd057611bd0611b67565b600063ffffffff80841680611c36577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611c6557611c65611b67565b0294935050505056fea164736f6c634300080f000a53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77001d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be496e697469616c697a61626c653a20636f6e7472616374206973206e6f742069a11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102415760003560e01c8063935f029e11610145578063dac6e63a116100bd578063f45e65d81161008c578063f8c68de011610071578063f8c68de014610597578063fd32aa0f1461059f578063ffa1ad74146105a757600080fd5b8063f45e65d81461057a578063f68016b71461058357600080fd5b8063dac6e63a1461054e578063e0e2016d14610556578063e81b2c6d1461055e578063f2fde38b1461056757600080fd5b8063bc49ce5f11610114578063c71973f6116100f9578063c71973f6146103f4578063c9b26f6114610407578063cc731b021461041a57600080fd5b8063bc49ce5f146103e4578063c4e8ddfa146103ec57600080fd5b8063935f029e146103ae5780639b7d7f0a146103c1578063a7119869146103c9578063b40a817c146103d157600080fd5b806348cd4cb1116101d857806354fd4d50116101a757806361d157681161018c57806361d1576814610380578063715018a6146103885780638da5cb5b1461039057600080fd5b806354fd4d501461032f5780635d73369c1461037857600080fd5b806348cd4cb1146102d75780634add321d146102df5780634d9f1559146103005780634f16540b1461030857600080fd5b80630c18c162116102145780630c18c162146102ab57806318d13918146102b457806319f5cea8146102c75780631fd19ee1146102cf57600080fd5b806306c9265714610246578063078f29cf146102615780630a49cb031461028e5780630bbb796814610296575b600080fd5b61024e6105af565b6040519081526020015b60405180910390f35b6102696105dd565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610258565b610269610616565b6102a96102a4366004611928565b610646565b005b61024e60655481565b6102a96102c2366004611a55565b610a44565b61024e610a58565b610269610a83565b61024e610aad565b6102e7610add565b60405167ffffffffffffffff9091168152602001610258565b610269610b03565b61024e7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c0881565b61036b6040518060400160405280600681526020017f312e31322e30000000000000000000000000000000000000000000000000000081525081565b6040516102589190611ae2565b61024e610b33565b61024e610b5e565b6102a9610b89565b60335473ffffffffffffffffffffffffffffffffffffffff16610269565b6102a96103bc366004611af5565b610b9d565b610269610bb3565b610269610be3565b6102a96103df366004611b17565b610c13565b61024e610c24565b610269610c4f565b6102a9610402366004611b32565b610c7f565b6102a9610415366004611b4e565b610c90565b6104de6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a0810191909152506040805160c08101825260695463ffffffff8082168352640100000000820460ff9081166020850152650100000000008304169383019390935266010000000000008104831660608301526a0100000000000000000000810490921660808201526e0100000000000000000000000000009091046fffffffffffffffffffffffffffffffff1660a082015290565b6040516102589190600060c08201905063ffffffff80845116835260ff602085015116602084015260ff6040850151166040840152806060850151166060840152806080850151166080840152506fffffffffffffffffffffffffffffffff60a08401511660a083015292915050565b610269610ca1565b61024e610cd1565b61024e60675481565b6102a9610575366004611a55565b610cfc565b61024e60665481565b6068546102e79067ffffffffffffffff1681565b61024e610db0565b61024e610ddb565b61024e600081565b6105da60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b81565b600061061161060d60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b5490565b905090565b600061061161060d60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b600054610100900460ff16158080156106665750600054600160ff909116105b806106805750303b158015610680575060005460ff166001145b610711576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561076f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b610777610e2a565b6107808a610cfc565b61078987610ec9565b6107938989610f2a565b61079c86610fbb565b6107c57f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08869055565b6107f86107f360017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b849055565b61082c61082660017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b83519055565b61086361085a60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60208401519055565b61089a61089160017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b60408401519055565b6108d16108c860017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b60608401519055565b6109086108ff60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b60808401519055565b61093f61093660017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b60a08401519055565b610947611099565b61095084611101565b610958610add565b67ffffffffffffffff168667ffffffffffffffff1610156109d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b8015610a3857600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b610a4c611575565b610a55816115f6565b50565b6105da60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b60006106117f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c085490565b600061061161060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b6069546000906106119063ffffffff6a0100000000000000000000820481169116611bad565b600061061161060d60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b6105da60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b6105da60017fe52a667f71ec761b9b381c7b76ca9b852adf7e8905da0e0ad49986a0a6871816611b96565b610b91611575565b610b9b600061167a565b565b610ba5611575565b610baf8282610f2a565b5050565b600061061161060d60017fa04c5bb938ca6fc46d95553abf0a76345ce3e722a30bf4f74928b8e7d852320d611b96565b600061061161060d60017f383f291819e6d54073bc9a648251d97421076bdd101933c0c022219ce9580637611b96565b610c1b611575565b610a5581610fbb565b6105da60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b600061061161060d60017f46adcbebc6be8ce551740c29c47c8798210f23f7f4086c41752944352568d5a8611b96565b610c87611575565b610a5581611101565b610c98611575565b610a5581610ec9565b600061061161060d60017f71ac12829d66ee73d8d95bff50b3589745ce57edae70a3fb111a2342464dc598611b96565b6105da60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b610d04611575565b73ffffffffffffffffffffffffffffffffffffffff8116610da7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610708565b610a558161167a565b6105da60017f9904ba90dde5696cda05c9e0dab5cbaa0fea005ace4d11218a02ac668dad6377611b96565b6105da60017f4b6c74f9e688cb39801f2112c14a8c57232a3fc5202e1444126d4bce86eb19ad611b96565b9055565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b5490565b600054610100900460ff16610ec1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b6116f1565b60678190556040805160208082018490528251808303909101815290820190915260005b60007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610f1e9190611ae2565b60405180910390a35050565b606582905560668190556040805160208101849052908101829052600090606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529050600160007f1d2b0bda21d56b8bd12d4f94ebacffdfb35f5e226f84b461103bb8beab6353be83604051610fae9190611ae2565b60405180910390a3505050565b610fc3610add565b67ffffffffffffffff168167ffffffffffffffff161015611040576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b606880547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff83169081179091556040805160208082019390935281518082039093018352810190526002610eed565b6110c761060d60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b600003610b9b57610b9b6110fc60017fa11ee3ab75b40e88a0105e935d17cd36c8faee0138320d776c411291bdbbb1a0611b96565b439055565b8060a001516fffffffffffffffffffffffffffffffff16816060015163ffffffff1611156111b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f53797374656d436f6e6669673a206d696e206261736520666565206d7573742060448201527f6265206c657373207468616e206d6178206261736500000000000000000000006064820152608401610708565b6001816040015160ff1611611248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a2064656e6f6d696e61746f72206d757374206260448201527f65206c6172676572207468616e203100000000000000000000000000000000006064820152608401610708565b6068546080820151825167ffffffffffffffff909216916112699190611bd9565b63ffffffff1611156112d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f53797374656d436f6e6669673a20676173206c696d697420746f6f206c6f77006044820152606401610708565b6000816020015160ff161161136e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f53797374656d436f6e6669673a20656c6173746963697479206d756c7469706c60448201527f6965722063616e6e6f74206265203000000000000000000000000000000000006064820152608401610708565b8051602082015163ffffffff82169160ff9091169061138e908290611bf8565b6113989190611c42565b63ffffffff161461142b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f53797374656d436f6e6669673a20707265636973696f6e206c6f73732077697460448201527f6820746172676574207265736f75726365206c696d69740000000000000000006064820152608401610708565b805160698054602084015160408501516060860151608087015160a09097015163ffffffff9687167fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000009095169490941764010000000060ff94851602177fffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffffff166501000000000093909216929092027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff1617660100000000000091851691909102177fffff0000000000000000000000000000000000000000ffffffffffffffffffff166a010000000000000000000093909416929092027fffff00000000000000000000000000000000ffffffffffffffffffffffffffff16929092176e0100000000000000000000000000006fffffffffffffffffffffffffffffffff90921691909102179055565b60335473ffffffffffffffffffffffffffffffffffffffff163314610b9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610708565b61161f7f65a7ed542fb37fe237fdfbdd70b31598523fe5b32879e307bae27a0bd9581c08829055565b6040805173ffffffffffffffffffffffffffffffffffffffff8316602082015260009101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290506003610eed565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600054610100900460ff16611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610708565b610b9b3361167a565b803573ffffffffffffffffffffffffffffffffffffffff811681146117b557600080fd5b919050565b803567ffffffffffffffff811681146117b557600080fd5b60405160c0810167ffffffffffffffff8111828210171561181c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803563ffffffff811681146117b557600080fd5b803560ff811681146117b557600080fd5b600060c0828403121561185957600080fd5b60405160c0810181811067ffffffffffffffff821117156118a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040529050806118b283611822565b81526118c060208401611836565b60208201526118d160408401611836565b60408201526118e260608401611822565b60608201526118f360808401611822565b608082015260a08301356fffffffffffffffffffffffffffffffff8116811461191b57600080fd5b60a0919091015292915050565b6000806000806000806000806000898b0361026081121561194857600080fd5b6119518b611791565b995060208b0135985060408b0135975060608b0135965061197460808c016117ba565b955061198260a08c01611791565b94506119918c60c08d01611847565b93506119a06101808c01611791565b925060c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe60820112156119d257600080fd5b506119db6117d2565b6119e86101a08c01611791565b81526119f76101c08c01611791565b6020820152611a096101e08c01611791565b6040820152611a1b6102008c01611791565b6060820152611a2d6102208c01611791565b6080820152611a3f6102408c01611791565b60a0820152809150509295985092959850929598565b600060208284031215611a6757600080fd5b611a7082611791565b9392505050565b6000815180845260005b81811015611a9d57602081850181015186830182015201611a81565b81811115611aaf576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611a706020830184611a77565b60008060408385031215611b0857600080fd5b50508035926020909101359150565b600060208284031215611b2957600080fd5b611a70826117ba565b600060c08284031215611b4457600080fd5b611a708383611847565b600060208284031215611b6057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015611ba857611ba8611b67565b500390565b600067ffffffffffffffff808316818516808303821115611bd057611bd0611b67565b01949350505050565b600063ffffffff808316818516808303821115611bd057611bd0611b67565b600063ffffffff80841680611c36577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b92169190910492915050565b600063ffffffff80831681851681830481118215151615611c6557611c65611b67565b0294935050505056fea164736f6c634300080f000a
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.