Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ProxyAdmin
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity 0.8.15; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { AddressManager } from "src/legacy/AddressManager.sol"; import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; import { Constants } from "src/libraries/Constants.sol"; /// @title IStaticERC1967Proxy /// @notice IStaticERC1967Proxy is a static version of the ERC1967 proxy interface. interface IStaticERC1967Proxy { function implementation() external view returns (address); function admin() external view returns (address); } /// @title IStaticL1ChugSplashProxy /// @notice IStaticL1ChugSplashProxy is a static version of the ChugSplash proxy interface. interface IStaticL1ChugSplashProxy { function getImplementation() external view returns (address); function getOwner() external view returns (address); } /// @title ProxyAdmin /// @notice This is an auxiliary contract meant to be assigned as the admin of an ERC1967 Proxy, /// based on the OpenZeppelin implementation. It has backwards compatibility logic to work /// with the various types of proxies that have been deployed by Optimism in the past. contract ProxyAdmin is Ownable { /// @notice The proxy types that the ProxyAdmin can manage. /// @custom:value ERC1967 Represents an ERC1967 compliant transparent proxy interface. /// @custom:value CHUGSPLASH Represents the Chugsplash proxy interface (legacy). /// @custom:value RESOLVED Represents the ResolvedDelegate proxy (legacy). enum ProxyType { ERC1967, CHUGSPLASH, RESOLVED } /// @notice A mapping of proxy types, used for backwards compatibility. mapping(address => ProxyType) public proxyType; /// @notice A reverse mapping of addresses to names held in the AddressManager. This must be /// manually kept up to date with changes in the AddressManager for this contract /// to be able to work as an admin for the ResolvedDelegateProxy type. mapping(address => string) public implementationName; /// @notice The address of the address manager, this is required to manage the /// ResolvedDelegateProxy type. AddressManager public addressManager; /// @notice A legacy upgrading indicator used by the old Chugsplash Proxy. bool internal upgrading; /// @param _owner Address of the initial owner of this contract. constructor(address _owner) Ownable() { _transferOwnership(_owner); } /// @notice Sets the proxy type for a given address. Only required for non-standard (legacy) /// proxy types. /// @param _address Address of the proxy. /// @param _type Type of the proxy. function setProxyType(address _address, ProxyType _type) external onlyOwner { proxyType[_address] = _type; } /// @notice Sets the implementation name for a given address. Only required for /// ResolvedDelegateProxy type proxies that have an implementation name. /// @param _address Address of the ResolvedDelegateProxy. /// @param _name Name of the implementation for the proxy. function setImplementationName(address _address, string memory _name) external onlyOwner { implementationName[_address] = _name; } /// @notice Set the address of the AddressManager. This is required to manage legacy /// ResolvedDelegateProxy type proxy contracts. /// @param _address Address of the AddressManager. function setAddressManager(AddressManager _address) external onlyOwner { addressManager = _address; } /// @custom:legacy /// @notice Set an address in the address manager. Since only the owner of the AddressManager /// can directly modify addresses and the ProxyAdmin will own the AddressManager, this /// gives the owner of the ProxyAdmin the ability to modify addresses directly. /// @param _name Name to set within the AddressManager. /// @param _address Address to attach to the given name. function setAddress(string memory _name, address _address) external onlyOwner { addressManager.setAddress(_name, _address); } /// @custom:legacy /// @notice Set the upgrading status for the Chugsplash proxy type. /// @param _upgrading Whether or not the system is upgrading. function setUpgrading(bool _upgrading) external onlyOwner { upgrading = _upgrading; } /// @custom:legacy /// @notice Legacy function used to tell ChugSplashProxy contracts if an upgrade is happening. /// @return Whether or not there is an upgrade going on. May not actually tell you whether an /// upgrade is going on, since we don't currently plan to use this variable for anything /// other than a legacy indicator to fix a UX bug in the ChugSplash proxy. function isUpgrading() external view returns (bool) { return upgrading; } /// @notice Returns the implementation of the given proxy address. /// @param _proxy Address of the proxy to get the implementation of. /// @return Address of the implementation of the proxy. function getProxyImplementation(address _proxy) external view returns (address) { ProxyType ptype = proxyType[_proxy]; if (ptype == ProxyType.ERC1967) { return IStaticERC1967Proxy(_proxy).implementation(); } else if (ptype == ProxyType.CHUGSPLASH) { return IStaticL1ChugSplashProxy(_proxy).getImplementation(); } else if (ptype == ProxyType.RESOLVED) { return addressManager.getAddress(implementationName[_proxy]); } else { revert("ProxyAdmin: unknown proxy type"); } } /// @notice Returns the admin of the given proxy address. /// @param _proxy Address of the proxy to get the admin of. /// @return Address of the admin of the proxy. function getProxyAdmin(address payable _proxy) external view returns (address) { ProxyType ptype = proxyType[_proxy]; if (ptype == ProxyType.ERC1967) { return IStaticERC1967Proxy(_proxy).admin(); } else if (ptype == ProxyType.CHUGSPLASH) { return IStaticL1ChugSplashProxy(_proxy).getOwner(); } else if (ptype == ProxyType.RESOLVED) { return addressManager.owner(); } else { revert("ProxyAdmin: unknown proxy type"); } } /// @notice Updates the admin of the given proxy address. /// @param _proxy Address of the proxy to update. /// @param _newAdmin Address of the new proxy admin. function changeProxyAdmin(address payable _proxy, address _newAdmin) external onlyOwner { ProxyType ptype = proxyType[_proxy]; if (ptype == ProxyType.ERC1967) { Proxy(_proxy).changeAdmin(_newAdmin); } else if (ptype == ProxyType.CHUGSPLASH) { L1ChugSplashProxy(_proxy).setOwner(_newAdmin); } else if (ptype == ProxyType.RESOLVED) { addressManager.transferOwnership(_newAdmin); } else { revert("ProxyAdmin: unknown proxy type"); } } /// @notice Changes a proxy's implementation contract. /// @param _proxy Address of the proxy to upgrade. /// @param _implementation Address of the new implementation address. function upgrade(address payable _proxy, address _implementation) public onlyOwner { ProxyType ptype = proxyType[_proxy]; if (ptype == ProxyType.ERC1967) { Proxy(_proxy).upgradeTo(_implementation); } else if (ptype == ProxyType.CHUGSPLASH) { L1ChugSplashProxy(_proxy).setStorage( Constants.PROXY_IMPLEMENTATION_ADDRESS, bytes32(uint256(uint160(_implementation))) ); } else if (ptype == ProxyType.RESOLVED) { string memory name = implementationName[_proxy]; addressManager.setAddress(name, _implementation); } else { // It should not be possible to retrieve a ProxyType value which is not matched by // one of the previous conditions. assert(false); } } /// @notice Changes a proxy's implementation contract and delegatecalls the new implementation /// with some given data. Useful for atomic upgrade-and-initialize calls. /// @param _proxy Address of the proxy to upgrade. /// @param _implementation Address of the new implementation address. /// @param _data Data to trigger the new implementation with. function upgradeAndCall( address payable _proxy, address _implementation, bytes memory _data ) external payable onlyOwner { ProxyType ptype = proxyType[_proxy]; if (ptype == ProxyType.ERC1967) { Proxy(_proxy).upgradeToAndCall{ value: msg.value }(_implementation, _data); } else { // reverts if proxy type is unknown upgrade(_proxy, _implementation); (bool success,) = _proxy.call{ value: msg.value }(_data); require(success, "ProxyAdmin: call to proxy after upgrade failed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _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); } }
// SPDX-License-Identifier: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity 0.8.15; import { Constants } from "src/libraries/Constants.sol"; /// @title Proxy /// @notice Proxy is a transparent proxy that passes through the call if the caller is the owner or /// if the caller is address(0), meaning that the call originated from an off-chain /// simulation. contract Proxy { /// @notice An event that is emitted each time the implementation is changed. This event is part /// of the EIP-1967 specification. /// @param implementation The address of the implementation contract event Upgraded(address indexed implementation); /// @notice An event that is emitted each time the owner is upgraded. This event is part of the /// EIP-1967 specification. /// @param previousAdmin The previous owner of the contract /// @param newAdmin The new owner of the contract event AdminChanged(address previousAdmin, address newAdmin); /// @notice A modifier that reverts if not called by the owner or by address(0) to allow /// eth_call to interact with this proxy without needing to use low-level storage /// inspection. We assume that nobody is able to trigger calls from address(0) during /// normal EVM execution. modifier proxyCallIfNotAdmin() { if (msg.sender == _getAdmin() || msg.sender == address(0)) { _; } else { // This WILL halt the call frame on completion. _doProxyCall(); } } /// @notice Sets the initial admin during contract deployment. Admin address is stored at the /// EIP-1967 admin storage slot so that accidental storage collision with the /// implementation is not possible. /// @param _admin Address of the initial contract admin. Admin as the ability to access the /// transparent proxy interface. constructor(address _admin) { _changeAdmin(_admin); } // slither-disable-next-line locked-ether receive() external payable { // Proxy call by default. _doProxyCall(); } // slither-disable-next-line locked-ether fallback() external payable { // Proxy call by default. _doProxyCall(); } /// @notice Set the implementation contract address. The code at the given address will execute /// when this contract is called. /// @param _implementation Address of the implementation contract. function upgradeTo(address _implementation) public virtual proxyCallIfNotAdmin { _setImplementation(_implementation); } /// @notice Set the implementation and call a function in a single transaction. Useful to ensure /// atomic execution of initialization-based upgrades. /// @param _implementation Address of the implementation contract. /// @param _data Calldata to delegatecall the new implementation with. function upgradeToAndCall( address _implementation, bytes calldata _data ) public payable virtual proxyCallIfNotAdmin returns (bytes memory) { _setImplementation(_implementation); (bool success, bytes memory returndata) = _implementation.delegatecall(_data); require(success, "Proxy: delegatecall to new implementation contract failed"); return returndata; } /// @notice Changes the owner of the proxy contract. Only callable by the owner. /// @param _admin New owner of the proxy contract. function changeAdmin(address _admin) public virtual proxyCallIfNotAdmin { _changeAdmin(_admin); } /// @notice Gets the owner of the proxy contract. /// @return Owner address. function admin() public virtual proxyCallIfNotAdmin returns (address) { return _getAdmin(); } //// @notice Queries the implementation address. /// @return Implementation address. function implementation() public virtual proxyCallIfNotAdmin returns (address) { return _getImplementation(); } /// @notice Sets the implementation address. /// @param _implementation New implementation address. function _setImplementation(address _implementation) internal { bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS; assembly { sstore(proxyImplementation, _implementation) } emit Upgraded(_implementation); } /// @notice Changes the owner of the proxy contract. /// @param _admin New owner of the proxy contract. function _changeAdmin(address _admin) internal { address previous = _getAdmin(); bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS; assembly { sstore(proxyOwner, _admin) } emit AdminChanged(previous, _admin); } /// @notice Performs the proxy call via a delegatecall. function _doProxyCall() internal { address impl = _getImplementation(); require(impl != address(0), "Proxy: implementation not initialized"); assembly { // Copy calldata into memory at 0x0....calldatasize. calldatacopy(0x0, 0x0, calldatasize()) // Perform the delegatecall, make sure to pass all available gas. let success := delegatecall(gas(), impl, 0x0, calldatasize(), 0x0, 0x0) // Copy returndata into memory at 0x0....returndatasize. Note that this *will* // overwrite the calldata that we just copied into memory but that doesn't really // matter because we'll be returning in a second anyway. returndatacopy(0x0, 0x0, returndatasize()) // Success == 0 means a revert. We'll revert too and pass the data up. if iszero(success) { revert(0x0, returndatasize()) } // Otherwise we'll just return and pass the data up. return(0x0, returndatasize()) } } /// @notice Queries the implementation address. /// @return Implementation address. function _getImplementation() internal view returns (address) { address impl; bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS; assembly { impl := sload(proxyImplementation) } return impl; } /// @notice Queries the owner of the proxy contract. /// @return Owner address. function _getAdmin() internal view returns (address) { address owner; bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS; assembly { owner := sload(proxyOwner) } return owner; } }
// SPDX-License-Identifier: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity 0.8.15; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; /// @custom:legacy /// @title AddressManager /// @notice AddressManager is a legacy contract that was used in the old version of the Optimism /// system to manage a registry of string names to addresses. We now use a more standard /// proxy system instead, but this contract is still necessary for backwards compatibility /// with several older contracts. contract AddressManager is Ownable { /// @notice Mapping of the hashes of string names to addresses. mapping(bytes32 => address) private addresses; /// @notice Emitted when an address is modified in the registry. /// @param name String name being set in the registry. /// @param newAddress Address set for the given name. /// @param oldAddress Address that was previously set for the given name. event AddressSet(string indexed name, address newAddress, address oldAddress); /// @notice Changes the address associated with a particular name. /// @param _name String name to associate an address with. /// @param _address Address to associate with the name. function setAddress(string memory _name, address _address) external onlyOwner { bytes32 nameHash = _getNameHash(_name); address oldAddress = addresses[nameHash]; addresses[nameHash] = _address; emit AddressSet(_name, _address, oldAddress); } /// @notice Retrieves the address associated with a given name. /// @param _name Name to retrieve an address for. /// @return Address associated with the given name. function getAddress(string memory _name) external view returns (address) { return addresses[_getNameHash(_name)]; } /// @notice Computes the hash of a name. /// @param _name Name to compute a hash for. /// @return Hash of the given name. function _getNameHash(string memory _name) internal pure returns (bytes32) { return keccak256(abi.encodePacked(_name)); } }
// SPDX-License-Identifier: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity 0.8.15; import { Constants } from "src/libraries/Constants.sol"; /// @title IL1ChugSplashDeployer interface IL1ChugSplashDeployer { function isUpgrading() external view returns (bool); } /// @custom:legacy /// @title L1ChugSplashProxy /// @notice Basic ChugSplash proxy contract for L1. Very close to being a normal proxy but has added /// functions `setCode` and `setStorage` for changing the code or storage of the contract. /// Note for future developers: do NOT make anything in this contract 'public' unless you /// know what you're doing. Anything public can potentially have a function signature that /// conflicts with a signature attached to the implementation contract. Public functions /// SHOULD always have the `proxyCallIfNotOwner` modifier unless there's some *really* good /// reason not to have that modifier. And there almost certainly is not a good reason to not /// have that modifier. Beware! contract L1ChugSplashProxy { /// @notice "Magic" prefix. When prepended to some arbitrary bytecode and used to create a /// contract, the appended bytecode will be deployed as given. bytes13 internal constant DEPLOY_CODE_PREFIX = 0x600D380380600D6000396000f3; /// @notice Blocks a function from being called when the parent signals that the system should /// be paused via an isUpgrading function. modifier onlyWhenNotPaused() { address owner = _getOwner(); // We do a low-level call because there's no guarantee that the owner actually *is* an // L1ChugSplashDeployer contract and Solidity will throw errors if we do a normal call and // it turns out that it isn't the right type of contract. (bool success, bytes memory returndata) = owner.staticcall(abi.encodeWithSelector(IL1ChugSplashDeployer.isUpgrading.selector)); // If the call was unsuccessful then we assume that there's no "isUpgrading" method and we // can just continue as normal. We also expect that the return value is exactly 32 bytes // long. If this isn't the case then we can safely ignore the result. if (success && returndata.length == 32) { // Although the expected value is a *boolean*, it's safer to decode as a uint256 in the // case that the isUpgrading function returned something other than 0 or 1. But we only // really care about the case where this value is 0 (= false). uint256 ret = abi.decode(returndata, (uint256)); require(ret == 0, "L1ChugSplashProxy: system is currently being upgraded"); } _; } /// @notice Makes a proxy call instead of triggering the given function when the caller is /// either the owner or the zero address. Caller can only ever be the zero address if /// this function is being called off-chain via eth_call, which is totally fine and can /// be convenient for client-side tooling. Avoids situations where the proxy and /// implementation share a sighash and the proxy function ends up being called instead /// of the implementation one. /// Note: msg.sender == address(0) can ONLY be triggered off-chain via eth_call. If /// there's a way for someone to send a transaction with msg.sender == address(0) in any /// real context then we have much bigger problems. Primary reason to include this /// additional allowed sender is because the owner address can be changed dynamically /// and we do not want clients to have to keep track of the current owner in order to /// make an eth_call that doesn't trigger the proxied contract. // slither-disable-next-line incorrect-modifier modifier proxyCallIfNotOwner() { if (msg.sender == _getOwner() || msg.sender == address(0)) { _; } else { // This WILL halt the call frame on completion. _doProxyCall(); } } /// @param _owner Address of the initial contract owner. constructor(address _owner) { _setOwner(_owner); } // slither-disable-next-line locked-ether receive() external payable { // Proxy call by default. _doProxyCall(); } // slither-disable-next-line locked-ether fallback() external payable { // Proxy call by default. _doProxyCall(); } /// @notice Sets the code that should be running behind this proxy. /// Note: This scheme is a bit different from the standard proxy scheme where one would /// typically deploy the code separately and then set the implementation address. We're /// doing it this way because it gives us a lot more freedom on the client side. Can /// only be triggered by the contract owner. /// @param _code New contract code to run inside this contract. function setCode(bytes memory _code) external proxyCallIfNotOwner { // Get the code hash of the current implementation. address implementation = _getImplementation(); // If the code hash matches the new implementation then we return early. if (keccak256(_code) == _getAccountCodeHash(implementation)) { return; } // Create the deploycode by appending the magic prefix. bytes memory deploycode = abi.encodePacked(DEPLOY_CODE_PREFIX, _code); // Deploy the code and set the new implementation address. address newImplementation; assembly { newImplementation := create(0x0, add(deploycode, 0x20), mload(deploycode)) } // Check that the code was actually deployed correctly. I'm not sure if you can ever // actually fail this check. Should only happen if the contract creation from above runs // out of gas but this parent execution thread does NOT run out of gas. Seems like we // should be doing this check anyway though. require( _getAccountCodeHash(newImplementation) == keccak256(_code), "L1ChugSplashProxy: code was not correctly deployed" ); _setImplementation(newImplementation); } /// @notice Modifies some storage slot within the proxy contract. Gives us a lot of power to /// perform upgrades in a more transparent way. Only callable by the owner. /// @param _key Storage key to modify. /// @param _value New value for the storage key. function setStorage(bytes32 _key, bytes32 _value) external proxyCallIfNotOwner { assembly { sstore(_key, _value) } } /// @notice Changes the owner of the proxy contract. Only callable by the owner. /// @param _owner New owner of the proxy contract. function setOwner(address _owner) external proxyCallIfNotOwner { _setOwner(_owner); } /// @notice Queries the owner of the proxy contract. Can only be called by the owner OR by /// making an eth_call and setting the "from" address to address(0). /// @return Owner address. function getOwner() external proxyCallIfNotOwner returns (address) { return _getOwner(); } /// @notice Queries the implementation address. Can only be called by the owner OR by making an /// eth_call and setting the "from" address to address(0). /// @return Implementation address. function getImplementation() external proxyCallIfNotOwner returns (address) { return _getImplementation(); } /// @notice Sets the implementation address. /// @param _implementation New implementation address. function _setImplementation(address _implementation) internal { bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS; assembly { sstore(proxyImplementation, _implementation) } } /// @notice Changes the owner of the proxy contract. /// @param _owner New owner of the proxy contract. function _setOwner(address _owner) internal { bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS; assembly { sstore(proxyOwner, _owner) } } /// @notice Performs the proxy call via a delegatecall. function _doProxyCall() internal onlyWhenNotPaused { address implementation = _getImplementation(); require(implementation != address(0), "L1ChugSplashProxy: implementation is not set yet"); assembly { // Copy calldata into memory at 0x0....calldatasize. calldatacopy(0x0, 0x0, calldatasize()) // Perform the delegatecall, make sure to pass all available gas. let success := delegatecall(gas(), implementation, 0x0, calldatasize(), 0x0, 0x0) // Copy returndata into memory at 0x0....returndatasize. Note that this *will* // overwrite the calldata that we just copied into memory but that doesn't really // matter because we'll be returning in a second anyway. returndatacopy(0x0, 0x0, returndatasize()) // Success == 0 means a revert. We'll revert too and pass the data up. if iszero(success) { revert(0x0, returndatasize()) } // Otherwise we'll just return and pass the data up. return(0x0, returndatasize()) } } /// @notice Queries the implementation address. /// @return Implementation address. function _getImplementation() internal view returns (address) { address implementation; bytes32 proxyImplementation = Constants.PROXY_IMPLEMENTATION_ADDRESS; assembly { implementation := sload(proxyImplementation) } return implementation; } /// @notice Queries the owner of the proxy contract. /// @return Owner address. function _getOwner() internal view returns (address) { address owner; bytes32 proxyOwner = Constants.PROXY_OWNER_ADDRESS; assembly { owner := sload(proxyOwner) } return owner; } /// @notice Gets the code hash for a given account. /// @param _account Address of the account to get a code hash for. /// @return Code hash for the account. function _getAccountCodeHash(address _account) internal view returns (bytes32) { bytes32 codeHash; assembly { codeHash := extcodehash(_account) } return codeHash; } }
// SPDX-License-Identifier: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity ^0.8.0; import { ResourceMetering } from "../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; } /// @notice The `reinitailizer` input for upgradable contracts. This value must be updated /// each time that the contracts are deployed. uint8 internal constant INITIALIZER = 1; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @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 Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity 0.8.15; import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { Burn } from "src/libraries/Burn.sol"; import { Arithmetic } from "src/libraries/Arithmetic.sol"; /// @custom:upgradeable /// @title ResourceMetering /// @notice ResourceMetering implements an EIP-1559 style resource metering system where pricing /// updates automatically based on current demand. abstract contract ResourceMetering is Initializable { /// @notice Represents the various parameters that control the way in which resources are /// metered. Corresponds to the EIP-1559 resource metering system. /// @custom:field prevBaseFee Base fee from the previous block(s). /// @custom:field prevBoughtGas Amount of gas bought so far in the current block. /// @custom:field prevBlockNum Last block number that the base fee was updated. struct ResourceParams { uint128 prevBaseFee; uint64 prevBoughtGas; uint64 prevBlockNum; } /// @notice Represents the configuration for the EIP-1559 based curve for the deposit gas /// market. These values should be set with care as it is possible to set them in /// a way that breaks the deposit gas market. The target resource limit is defined as /// maxResourceLimit / elasticityMultiplier. This struct was designed to fit within a /// single word. There is additional space for additions in the future. /// @custom:field maxResourceLimit Represents the maximum amount of deposit gas that /// can be purchased per block. /// @custom:field elasticityMultiplier Determines the target resource limit along with /// the resource limit. /// @custom:field baseFeeMaxChangeDenominator Determines max change on fee per block. /// @custom:field minimumBaseFee The min deposit base fee, it is clamped to this /// value. /// @custom:field systemTxMaxGas The amount of gas supplied to the system /// transaction. This should be set to the same /// number that the op-node sets as the gas limit /// for the system transaction. /// @custom:field maximumBaseFee The max deposit base fee, it is clamped to this /// value. struct ResourceConfig { uint32 maxResourceLimit; uint8 elasticityMultiplier; uint8 baseFeeMaxChangeDenominator; uint32 minimumBaseFee; uint32 systemTxMaxGas; uint128 maximumBaseFee; } /// @notice EIP-1559 style gas parameters. ResourceParams public params; /// @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades. uint256[48] private __gap; /// @notice Meters access to a function based an amount of a requested resource. /// @param _amount Amount of the resource requested. modifier metered(uint64 _amount) { // Record initial gas amount so we can refund for it later. uint256 initialGas = gasleft(); // Run the underlying function. _; // Run the metering function. _metered(_amount, initialGas); } /// @notice An internal function that holds all of the logic for metering a resource. /// @param _amount Amount of the resource requested. /// @param _initialGas The amount of gas before any modifier execution. function _metered(uint64 _amount, uint256 _initialGas) internal { // Update block number and base fee if necessary. uint256 blockDiff = block.number - params.prevBlockNum; ResourceConfig memory config = _resourceConfig(); int256 targetResourceLimit = int256(uint256(config.maxResourceLimit)) / int256(uint256(config.elasticityMultiplier)); if (blockDiff > 0) { // Handle updating EIP-1559 style gas parameters. We use EIP-1559 to restrict the rate // at which deposits can be created and therefore limit the potential for deposits to // spam the L2 system. Fee scheme is very similar to EIP-1559 with minor changes. int256 gasUsedDelta = int256(uint256(params.prevBoughtGas)) - targetResourceLimit; int256 baseFeeDelta = (int256(uint256(params.prevBaseFee)) * gasUsedDelta) / (targetResourceLimit * int256(uint256(config.baseFeeMaxChangeDenominator))); // Update base fee by adding the base fee delta and clamp the resulting value between // min and max. int256 newBaseFee = Arithmetic.clamp({ _value: int256(uint256(params.prevBaseFee)) + baseFeeDelta, _min: int256(uint256(config.minimumBaseFee)), _max: int256(uint256(config.maximumBaseFee)) }); // If we skipped more than one block, we also need to account for every empty block. // Empty block means there was no demand for deposits in that block, so we should // reflect this lack of demand in the fee. if (blockDiff > 1) { // Update the base fee by repeatedly applying the exponent 1-(1/change_denominator) // blockDiff - 1 times. Simulates multiple empty blocks. Clamp the resulting value // between min and max. newBaseFee = Arithmetic.clamp({ _value: Arithmetic.cdexp({ _coefficient: newBaseFee, _denominator: int256(uint256(config.baseFeeMaxChangeDenominator)), _exponent: int256(blockDiff - 1) }), _min: int256(uint256(config.minimumBaseFee)), _max: int256(uint256(config.maximumBaseFee)) }); } // Update new base fee, reset bought gas, and update block number. params.prevBaseFee = uint128(uint256(newBaseFee)); params.prevBoughtGas = 0; params.prevBlockNum = uint64(block.number); } // Make sure we can actually buy the resource amount requested by the user. params.prevBoughtGas += _amount; require( int256(uint256(params.prevBoughtGas)) <= int256(uint256(config.maxResourceLimit)), "ResourceMetering: cannot buy more gas than available gas limit" ); // Determine the amount of ETH to be paid. uint256 resourceCost = uint256(_amount) * uint256(params.prevBaseFee); // We currently charge for this ETH amount as an L1 gas burn, so we convert the ETH amount // into gas by dividing by the L1 base fee. We assume a minimum base fee of 1 gwei to avoid // division by zero for L1s that don't support 1559 or to avoid excessive gas burns during // periods of extremely low L1 demand. One-day average gas fee hasn't dipped below 1 gwei // during any 1 day period in the last 5 years, so should be fine. uint256 gasCost = resourceCost / Math.max(block.basefee, 1 gwei); // Give the user a refund based on the amount of gas they used to do all of the work up to // this point. Since we're at the end of the modifier, this should be pretty accurate. Acts // effectively like a dynamic stipend (with a minimum value). uint256 usedGas = _initialGas - gasleft(); if (gasCost > usedGas) { Burn.gas(gasCost - usedGas); } } /// @notice Virtual function that returns the resource config. /// Contracts that inherit this contract must implement this function. /// @return ResourceConfig function _resourceConfig() internal virtual returns (ResourceConfig memory); /// @notice Sets initial resource parameter values. /// This function must either be called by the initializer function of an upgradeable /// child contract. // solhint-disable-next-line func-name-mixedcase function __ResourceMetering_init() internal onlyInitializing { if (params.prevBlockNum == 0) { params = ResourceParams({ prevBaseFee: 1 gwei, prevBoughtGas: 0, prevBlockNum: uint64(block.number) }); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (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: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. 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: BSL 1.1 - Copyright 2024 MetaLayer Labs Ltd. pragma solidity 0.8.15; 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 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/", "forge-std/=lib/forge-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "safe-contracts/=lib/safe-contracts/contracts/", "clones-with-immutable-args/=lib/clones-with-immutable-args/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "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
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"addressManager","outputs":[{"internalType":"contract AddressManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_proxy","type":"address"},{"internalType":"address","name":"_newAdmin","type":"address"}],"name":"changeProxyAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_proxy","type":"address"}],"name":"getProxyAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_proxy","type":"address"}],"name":"getProxyImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"implementationName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isUpgrading","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"proxyType","outputs":[{"internalType":"enum ProxyAdmin.ProxyType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_address","type":"address"}],"name":"setAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AddressManager","name":"_address","type":"address"}],"name":"setAddressManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"name":"setImplementationName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"enum ProxyAdmin.ProxyType","name":"_type","type":"uint8"}],"name":"setProxyType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_upgrading","type":"bool"}],"name":"setUpgrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_proxy","type":"address"},{"internalType":"address","name":"_implementation","type":"address"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_proxy","type":"address"},{"internalType":"address","name":"_implementation","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"upgradeAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5060405161152238038061152283398101604081905261002f91610097565b61003833610047565b61004181610047565b506100c7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100a957600080fd5b81516001600160a01b03811681146100c057600080fd5b9392505050565b61144c806100d66000396000f3fe6080604052600436106100fe5760003560e01c8063860f7cda1161009557806399a88ec41161006457806399a88ec4146102b25780639b2ea4bd146102d2578063b7947262146102f2578063f2fde38b1461031c578063f3b7dead1461033c57600080fd5b8063860f7cda146102415780638d52d4a0146102615780638da5cb5b146102815780639623609d1461029f57600080fd5b80633ab76e9f116100d15780633ab76e9f146101af5780636bd9f516146101cf578063715018a61461020c5780637eff275e1461022157600080fd5b80630652b57a1461010357806307c8f7b014610125578063204e1c7a14610145578063238181ae14610182575b600080fd5b34801561010f57600080fd5b5061012361011e366004610e31565b61035c565b005b34801561013157600080fd5b50610123610140366004610e4e565b610386565b34801561015157600080fd5b50610165610160366004610e31565b6103ac565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561018e57600080fd5b506101a261019d366004610e31565b61056b565b6040516101799190610ec8565b3480156101bb57600080fd5b50600354610165906001600160a01b031681565b3480156101db57600080fd5b506101ff6101ea366004610e31565b60016020526000908152604090205460ff1681565b6040516101799190610ef1565b34801561021857600080fd5b50610123610605565b34801561022d57600080fd5b5061012361023c366004610f19565b610619565b34801561024d57600080fd5b5061012361025c36600461101f565b61074d565b34801561026d57600080fd5b5061012361027c36600461106f565b610777565b34801561028d57600080fd5b506000546001600160a01b0316610165565b6101236102ad3660046110a1565b6107c0565b3480156102be57600080fd5b506101236102cd366004610f19565b610950565b3480156102de57600080fd5b506101236102ed366004611117565b610b54565b3480156102fe57600080fd5b50600354600160a01b900460ff166040519015158152602001610179565b34801561032857600080fd5b50610123610337366004610e31565b610bc4565b34801561034857600080fd5b50610165610357366004610e31565b610c3d565b610364610d72565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b61038e610d72565b60038054911515600160a01b0260ff60a01b19909216919091179055565b6001600160a01b03811660009081526001602052604081205460ff16818160028111156103db576103db610edb565b0361044957826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610442919061115e565b9392505050565b600181600281111561045d5761045d610edb565b036104a057826001600160a01b031663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b60028160028111156104b4576104b4610edb565b03610518576003546001600160a01b0384811660009081526002602052604090819020905163bf40fac160e01b8152919092169163bf40fac1916104fb91906004016111af565b602060405180830381865afa15801561041e573d6000803e3d6000fd5b60405162461bcd60e51b815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b600260205260009081526040902080546105849061117b565b80601f01602080910402602001604051908101604052809291908181526020018280546105b09061117b565b80156105fd5780601f106105d2576101008083540402835291602001916105fd565b820191906000526020600020905b8154815290600101906020018083116105e057829003601f168201915b505050505081565b61060d610d72565b6106176000610dcc565b565b610621610d72565b6001600160a01b03821660009081526001602052604081205460ff169081600281111561065057610650610edb565b036106b6576040516308f2839760e41b81526001600160a01b038381166004830152841690638f283970906024015b600060405180830381600087803b15801561069957600080fd5b505af11580156106ad573d6000803e3d6000fd5b50505050505050565b60018160028111156106ca576106ca610edb565b036106fd576040516313af403560e01b81526001600160a01b0383811660048301528416906313af40359060240161067f565b600281600281111561071157610711610edb565b036105185760035460405163f2fde38b60e01b81526001600160a01b0384811660048301529091169063f2fde38b9060240161067f565b505050565b610755610d72565b6001600160a01b03821660009081526002602052604090206107488282611280565b61077f610d72565b6001600160a01b03821660009081526001602081905260409091208054839260ff19909116908360028111156107b7576107b7610edb565b02179055505050565b6107c8610d72565b6001600160a01b03831660009081526001602052604081205460ff16908160028111156107f7576107f7610edb565b036108795760405163278f794360e11b81526001600160a01b03851690634f1ef28690349061082c9087908790600401611340565b60006040518083038185885af115801561084a573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052610873919081019061136c565b5061094a565b6108838484610950565b6000846001600160a01b0316348460405161089e91906113e3565b60006040518083038185875af1925050503d80600081146108db576040519150601f19603f3d011682016040523d82523d6000602084013e6108e0565b606091505b50509050806109485760405162461bcd60e51b815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201526d1d5c19dc9859194819985a5b195960921b606482015260840161055c565b505b50505050565b610958610d72565b6001600160a01b03821660009081526001602052604081205460ff169081600281111561098757610987610edb565b036109ba57604051631b2ce7f360e11b81526001600160a01b038381166004830152841690633659cfe69060240161067f565b60018160028111156109ce576109ce610edb565b03610a2757604051634d8587ed60e11b81527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60048201526001600160a01b038381166024830152841690639b0b0fda9060440161067f565b6002816002811115610a3b57610a3b610edb565b03610b4c576001600160a01b03831660009081526002602052604081208054610a639061117b565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8f9061117b565b8015610adc5780601f10610ab157610100808354040283529160200191610adc565b820191906000526020600020905b815481529060010190602001808311610abf57829003601f168201915b5050600354604051639b2ea4bd60e01b81529495506001600160a01b031693639b2ea4bd9350610b14925085915087906004016113ff565b600060405180830381600087803b158015610b2e57600080fd5b505af1158015610b42573d6000803e3d6000fd5b5050505050505050565b610748611429565b610b5c610d72565b600354604051639b2ea4bd60e01b81526001600160a01b0390911690639b2ea4bd90610b8e90859085906004016113ff565b600060405180830381600087803b158015610ba857600080fd5b505af1158015610bbc573d6000803e3d6000fd5b505050505050565b610bcc610d72565b6001600160a01b038116610c315760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161055c565b610c3a81610dcc565b50565b6001600160a01b03811660009081526001602052604081205460ff1681816002811115610c6c57610c6c610edb565b03610caf57826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b6001816002811115610cc357610cc3610edb565b03610d0657826001600160a01b031663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b6002816002811115610d1a57610d1a610edb565b0361051857600360009054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b6000546001600160a01b031633146106175760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161055c565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610c3a57600080fd5b600060208284031215610e4357600080fd5b813561044281610e1c565b600060208284031215610e6057600080fd5b8135801515811461044257600080fd5b60005b83811015610e8b578181015183820152602001610e73565b8381111561094a5750506000910152565b60008151808452610eb4816020860160208601610e70565b601f01601f19169290920160200192915050565b6020815260006104426020830184610e9c565b634e487b7160e01b600052602160045260246000fd5b6020810160038310610f1357634e487b7160e01b600052602160045260246000fd5b91905290565b60008060408385031215610f2c57600080fd5b8235610f3781610e1c565b91506020830135610f4781610e1c565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610f9157610f91610f52565b604052919050565b600067ffffffffffffffff821115610fb357610fb3610f52565b50601f01601f191660200190565b6000610fd4610fcf84610f99565b610f68565b9050828152838383011115610fe857600080fd5b828260208301376000602084830101529392505050565b600082601f83011261101057600080fd5b61044283833560208501610fc1565b6000806040838503121561103257600080fd5b823561103d81610e1c565b9150602083013567ffffffffffffffff81111561105957600080fd5b61106585828601610fff565b9150509250929050565b6000806040838503121561108257600080fd5b823561108d81610e1c565b9150602083013560038110610f4757600080fd5b6000806000606084860312156110b657600080fd5b83356110c181610e1c565b925060208401356110d181610e1c565b9150604084013567ffffffffffffffff8111156110ed57600080fd5b8401601f810186136110fe57600080fd5b61110d86823560208401610fc1565b9150509250925092565b6000806040838503121561112a57600080fd5b823567ffffffffffffffff81111561114157600080fd5b61114d85828601610fff565b9250506020830135610f4781610e1c565b60006020828403121561117057600080fd5b815161044281610e1c565b600181811c9082168061118f57607f821691505b60208210810361056557634e487b7160e01b600052602260045260246000fd5b60006020808352600084546111c38161117b565b808487015260406001808416600081146111e457600181146111fe5761122c565b60ff1985168984015283151560051b89018301955061122c565b896000528660002060005b858110156112245781548b8201860152908301908801611209565b8a0184019650505b509398975050505050505050565b601f82111561074857600081815260208120601f850160051c810160208610156112615750805b601f850160051c820191505b81811015610bbc5782815560010161126d565b815167ffffffffffffffff81111561129a5761129a610f52565b6112ae816112a8845461117b565b8461123a565b602080601f8311600181146112e357600084156112cb5750858301515b600019600386901b1c1916600185901b178555610bbc565b600085815260208120601f198616915b82811015611312578886015182559484019460019091019084016112f3565b50858210156113305787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038316815260406020820181905260009061136490830184610e9c565b949350505050565b60006020828403121561137e57600080fd5b815167ffffffffffffffff81111561139557600080fd5b8201601f810184136113a657600080fd5b80516113b4610fcf82610f99565b8181528560208385010111156113c957600080fd5b6113da826020830160208601610e70565b95945050505050565b600082516113f5818460208701610e70565b9190910192915050565b6040815260006114126040830185610e9c565b905060018060a01b03831660208301529392505050565b634e487b7160e01b600052600160045260246000fdfea164736f6c634300080f000a000000000000000000000000263efb012774435effb168f9ebd94f7b03bdb825
Deployed Bytecode
0x6080604052600436106100fe5760003560e01c8063860f7cda1161009557806399a88ec41161006457806399a88ec4146102b25780639b2ea4bd146102d2578063b7947262146102f2578063f2fde38b1461031c578063f3b7dead1461033c57600080fd5b8063860f7cda146102415780638d52d4a0146102615780638da5cb5b146102815780639623609d1461029f57600080fd5b80633ab76e9f116100d15780633ab76e9f146101af5780636bd9f516146101cf578063715018a61461020c5780637eff275e1461022157600080fd5b80630652b57a1461010357806307c8f7b014610125578063204e1c7a14610145578063238181ae14610182575b600080fd5b34801561010f57600080fd5b5061012361011e366004610e31565b61035c565b005b34801561013157600080fd5b50610123610140366004610e4e565b610386565b34801561015157600080fd5b50610165610160366004610e31565b6103ac565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561018e57600080fd5b506101a261019d366004610e31565b61056b565b6040516101799190610ec8565b3480156101bb57600080fd5b50600354610165906001600160a01b031681565b3480156101db57600080fd5b506101ff6101ea366004610e31565b60016020526000908152604090205460ff1681565b6040516101799190610ef1565b34801561021857600080fd5b50610123610605565b34801561022d57600080fd5b5061012361023c366004610f19565b610619565b34801561024d57600080fd5b5061012361025c36600461101f565b61074d565b34801561026d57600080fd5b5061012361027c36600461106f565b610777565b34801561028d57600080fd5b506000546001600160a01b0316610165565b6101236102ad3660046110a1565b6107c0565b3480156102be57600080fd5b506101236102cd366004610f19565b610950565b3480156102de57600080fd5b506101236102ed366004611117565b610b54565b3480156102fe57600080fd5b50600354600160a01b900460ff166040519015158152602001610179565b34801561032857600080fd5b50610123610337366004610e31565b610bc4565b34801561034857600080fd5b50610165610357366004610e31565b610c3d565b610364610d72565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b61038e610d72565b60038054911515600160a01b0260ff60a01b19909216919091179055565b6001600160a01b03811660009081526001602052604081205460ff16818160028111156103db576103db610edb565b0361044957826001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610442919061115e565b9392505050565b600181600281111561045d5761045d610edb565b036104a057826001600160a01b031663aaf10f426040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b60028160028111156104b4576104b4610edb565b03610518576003546001600160a01b0384811660009081526002602052604090819020905163bf40fac160e01b8152919092169163bf40fac1916104fb91906004016111af565b602060405180830381865afa15801561041e573d6000803e3d6000fd5b60405162461bcd60e51b815260206004820152601e60248201527f50726f787941646d696e3a20756e6b6e6f776e2070726f78792074797065000060448201526064015b60405180910390fd5b50919050565b600260205260009081526040902080546105849061117b565b80601f01602080910402602001604051908101604052809291908181526020018280546105b09061117b565b80156105fd5780601f106105d2576101008083540402835291602001916105fd565b820191906000526020600020905b8154815290600101906020018083116105e057829003601f168201915b505050505081565b61060d610d72565b6106176000610dcc565b565b610621610d72565b6001600160a01b03821660009081526001602052604081205460ff169081600281111561065057610650610edb565b036106b6576040516308f2839760e41b81526001600160a01b038381166004830152841690638f283970906024015b600060405180830381600087803b15801561069957600080fd5b505af11580156106ad573d6000803e3d6000fd5b50505050505050565b60018160028111156106ca576106ca610edb565b036106fd576040516313af403560e01b81526001600160a01b0383811660048301528416906313af40359060240161067f565b600281600281111561071157610711610edb565b036105185760035460405163f2fde38b60e01b81526001600160a01b0384811660048301529091169063f2fde38b9060240161067f565b505050565b610755610d72565b6001600160a01b03821660009081526002602052604090206107488282611280565b61077f610d72565b6001600160a01b03821660009081526001602081905260409091208054839260ff19909116908360028111156107b7576107b7610edb565b02179055505050565b6107c8610d72565b6001600160a01b03831660009081526001602052604081205460ff16908160028111156107f7576107f7610edb565b036108795760405163278f794360e11b81526001600160a01b03851690634f1ef28690349061082c9087908790600401611340565b60006040518083038185885af115801561084a573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f19168201604052610873919081019061136c565b5061094a565b6108838484610950565b6000846001600160a01b0316348460405161089e91906113e3565b60006040518083038185875af1925050503d80600081146108db576040519150601f19603f3d011682016040523d82523d6000602084013e6108e0565b606091505b50509050806109485760405162461bcd60e51b815260206004820152602e60248201527f50726f787941646d696e3a2063616c6c20746f2070726f78792061667465722060448201526d1d5c19dc9859194819985a5b195960921b606482015260840161055c565b505b50505050565b610958610d72565b6001600160a01b03821660009081526001602052604081205460ff169081600281111561098757610987610edb565b036109ba57604051631b2ce7f360e11b81526001600160a01b038381166004830152841690633659cfe69060240161067f565b60018160028111156109ce576109ce610edb565b03610a2757604051634d8587ed60e11b81527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60048201526001600160a01b038381166024830152841690639b0b0fda9060440161067f565b6002816002811115610a3b57610a3b610edb565b03610b4c576001600160a01b03831660009081526002602052604081208054610a639061117b565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8f9061117b565b8015610adc5780601f10610ab157610100808354040283529160200191610adc565b820191906000526020600020905b815481529060010190602001808311610abf57829003601f168201915b5050600354604051639b2ea4bd60e01b81529495506001600160a01b031693639b2ea4bd9350610b14925085915087906004016113ff565b600060405180830381600087803b158015610b2e57600080fd5b505af1158015610b42573d6000803e3d6000fd5b5050505050505050565b610748611429565b610b5c610d72565b600354604051639b2ea4bd60e01b81526001600160a01b0390911690639b2ea4bd90610b8e90859085906004016113ff565b600060405180830381600087803b158015610ba857600080fd5b505af1158015610bbc573d6000803e3d6000fd5b505050505050565b610bcc610d72565b6001600160a01b038116610c315760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161055c565b610c3a81610dcc565b50565b6001600160a01b03811660009081526001602052604081205460ff1681816002811115610c6c57610c6c610edb565b03610caf57826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b6001816002811115610cc357610cc3610edb565b03610d0657826001600160a01b031663893d20e86040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b6002816002811115610d1a57610d1a610edb565b0361051857600360009054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561041e573d6000803e3d6000fd5b6000546001600160a01b031633146106175760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161055c565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381168114610c3a57600080fd5b600060208284031215610e4357600080fd5b813561044281610e1c565b600060208284031215610e6057600080fd5b8135801515811461044257600080fd5b60005b83811015610e8b578181015183820152602001610e73565b8381111561094a5750506000910152565b60008151808452610eb4816020860160208601610e70565b601f01601f19169290920160200192915050565b6020815260006104426020830184610e9c565b634e487b7160e01b600052602160045260246000fd5b6020810160038310610f1357634e487b7160e01b600052602160045260246000fd5b91905290565b60008060408385031215610f2c57600080fd5b8235610f3781610e1c565b91506020830135610f4781610e1c565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610f9157610f91610f52565b604052919050565b600067ffffffffffffffff821115610fb357610fb3610f52565b50601f01601f191660200190565b6000610fd4610fcf84610f99565b610f68565b9050828152838383011115610fe857600080fd5b828260208301376000602084830101529392505050565b600082601f83011261101057600080fd5b61044283833560208501610fc1565b6000806040838503121561103257600080fd5b823561103d81610e1c565b9150602083013567ffffffffffffffff81111561105957600080fd5b61106585828601610fff565b9150509250929050565b6000806040838503121561108257600080fd5b823561108d81610e1c565b9150602083013560038110610f4757600080fd5b6000806000606084860312156110b657600080fd5b83356110c181610e1c565b925060208401356110d181610e1c565b9150604084013567ffffffffffffffff8111156110ed57600080fd5b8401601f810186136110fe57600080fd5b61110d86823560208401610fc1565b9150509250925092565b6000806040838503121561112a57600080fd5b823567ffffffffffffffff81111561114157600080fd5b61114d85828601610fff565b9250506020830135610f4781610e1c565b60006020828403121561117057600080fd5b815161044281610e1c565b600181811c9082168061118f57607f821691505b60208210810361056557634e487b7160e01b600052602260045260246000fd5b60006020808352600084546111c38161117b565b808487015260406001808416600081146111e457600181146111fe5761122c565b60ff1985168984015283151560051b89018301955061122c565b896000528660002060005b858110156112245781548b8201860152908301908801611209565b8a0184019650505b509398975050505050505050565b601f82111561074857600081815260208120601f850160051c810160208610156112615750805b601f850160051c820191505b81811015610bbc5782815560010161126d565b815167ffffffffffffffff81111561129a5761129a610f52565b6112ae816112a8845461117b565b8461123a565b602080601f8311600181146112e357600084156112cb5750858301515b600019600386901b1c1916600185901b178555610bbc565b600085815260208120601f198616915b82811015611312578886015182559484019460019091019084016112f3565b50858210156113305787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038316815260406020820181905260009061136490830184610e9c565b949350505050565b60006020828403121561137e57600080fd5b815167ffffffffffffffff81111561139557600080fd5b8201601f810184136113a657600080fd5b80516113b4610fcf82610f99565b8181528560208385010111156113c957600080fd5b6113da826020830160208601610e70565b95945050505050565b600082516113f5818460208701610e70565b9190910192915050565b6040815260006114126040830185610e9c565b905060018060a01b03831660208301529392505050565b634e487b7160e01b600052600160045260246000fdfea164736f6c634300080f000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000263efb012774435effb168f9ebd94f7b03bdb825
-----Decoded View---------------
Arg [0] : _owner (address): 0x263EFB012774435efFB168f9Ebd94f7b03BDb825
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000263efb012774435effb168f9ebd94f7b03bdb825
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
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.