Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 14547459 | 829 days ago | IN | Create: Unlock | 0 ETH | 0.14304763 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Unlock
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 80 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; /** * @title The Unlock contract * @author Julien Genestoux (unlock-protocol.com) * This smart contract has 3 main roles: * 1. Distribute discounts to discount token holders * 2. Grant dicount tokens to users making referrals and/or publishers granting discounts. * 3. Create & deploy Public Lock contracts. * In order to achieve these 3 elements, it keeps track of several things such as * a. Deployed locks addresses and balances of discount tokens granted by each lock. * b. The total network product (sum of all key sales, net of discounts) * c. Total of discounts granted * d. Balances of discount tokens, including 'frozen' tokens (which have been used to claim * discounts and cannot be used/transferred for a given period) * e. Growth rate of Network Product * f. Growth rate of Discount tokens supply * The smart contract has an owner who only can perform the following * - Upgrades * - Change in golden rules (20% of GDP available in discounts, and supply growth rate is at most * 50% of GNP growth rate) * NOTE: This smart contract is partially implemented for now until enough Locks are deployed and * in the wild. * The partial implementation includes the following features: * a. Keeping track of deployed locks * b. Keeping track of GNP */ import '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol'; import '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol'; import 'hardlydifficult-eth/contracts/protocols/Uniswap/IUniswapOracle.sol'; import './utils/UnlockOwnable.sol'; import './utils/UnlockInitializable.sol'; import './interfaces/IPublicLock.sol'; import './interfaces/IMintableERC20.sol'; /// @dev Must list the direct base contracts in the order from “most base-like” to “most derived”. /// https://solidity.readthedocs.io/en/latest/contracts.html#multiple-inheritance-and-linearization contract Unlock is UnlockInitializable, UnlockOwnable { /** * The struct for a lock * We use deployed to keep track of deployments. * This is required because both totalSales and yieldedDiscountTokens are 0 when initialized, * which would be the same values when the lock is not set. */ struct LockBalances { bool deployed; uint totalSales; // This is in wei uint yieldedDiscountTokens; } modifier onlyFromDeployedLock() { require(locks[msg.sender].deployed, 'ONLY_LOCKS'); _; } uint public grossNetworkProduct; uint public totalDiscountGranted; // We keep track of deployed locks to ensure that callers are all deployed locks. mapping (address => LockBalances) public locks; // global base token URI // Used by locks where the owner has not set a custom base URI. string public globalBaseTokenURI; // global base token symbol // Used by locks where the owner has not set a custom symbol string public globalTokenSymbol; // The address of the latest public lock template, used by default when `createLock` is called address public publicLockAddress; // Map token address to oracle contract address if the token is supported // Used for GDP calculations mapping (address => IUniswapOracle) public uniswapOracles; // The WETH token address, used for value calculations address public weth; // The UDT token address, used to mint tokens on referral address public udt; // The approx amount of gas required to purchase a key uint public estimatedGasForPurchase; // Blockchain ID the network id on which this version of Unlock is operating uint public chainId; // store proxy admin address public proxyAdminAddress; ProxyAdmin private proxyAdmin; // publicLock templates mapping(address => uint16) private _publicLockVersions; mapping(uint16 => address) private _publicLockImpls; uint16 public publicLockLatestVersion; // Events event NewLock( address indexed lockOwner, address indexed newLockAddress ); event LockUpgraded( address lockAddress, uint16 version ); event ConfigUnlock( address udt, address weth, uint estimatedGasForPurchase, string globalTokenSymbol, string globalTokenURI, uint chainId ); event SetLockTemplate( address publicLockAddress ); event GNPChanged( uint grossNetworkProduct, uint _valueInETH, address tokenAddress, uint value, address lockAddress ); event ResetTrackedValue( uint grossNetworkProduct, uint totalDiscountGranted ); event UnlockTemplateAdded( address indexed impl, uint16 indexed version ); // Use initialize instead of a constructor to support proxies (for upgradeability via OZ). function initialize( address _unlockOwner ) public initializer() { // We must manually initialize Ownable UnlockOwnable.__initializeOwnable(_unlockOwner); // add a proxy admin on deployment _deployProxyAdmin(); } function initializeProxyAdmin() public onlyOwner { require(proxyAdminAddress == address(0), "ALREADY_DEPLOYED"); _deployProxyAdmin(); } /** * @dev Deploy the ProxyAdmin contract that will manage lock templates upgrades * This deploys an instance of ProxyAdmin used by PublicLock transparent proxies. */ function _deployProxyAdmin() private returns(address) { proxyAdmin = new ProxyAdmin(); proxyAdminAddress = address(proxyAdmin); return address(proxyAdmin); } /** * @dev Helper to get the version number of a template from his address */ function publicLockVersions(address _impl) external view returns(uint16) { return _publicLockVersions[_impl]; } /** * @dev Helper to get the address of a template based on its version number */ function publicLockImpls(uint16 _version) external view returns(address) { return _publicLockImpls[_version]; } /** * @dev Registers a new PublicLock template immplementation * The template is identified by a version number * Once registered, the template can be used to upgrade an existing Lock */ function addLockTemplate(address impl, uint16 version) public onlyOwner { _publicLockVersions[impl] = version; _publicLockImpls[version] = impl; if (publicLockLatestVersion < version) publicLockLatestVersion = version; emit UnlockTemplateAdded(impl, version); } /** * @notice Create lock (legacy) * This deploys a lock for a creator. It also keeps track of the deployed lock. * @param _expirationDuration the duration of the lock (pass type(uint).max for unlimited duration) * @param _tokenAddress set to the ERC20 token address, or 0 for ETH. * @param _keyPrice the price of each key * @param _maxNumberOfKeys the maximum nimbers of keys to be edited * @param _lockName the name of the lock * param _salt [deprec] -- kept only for backwards copatibility * This may be implemented as a sequence ID or with RNG. It's used with `create2` * to know the lock's address before the transaction is mined. * @dev internally call `createUpgradeableLock` */ function createLock( uint _expirationDuration, address _tokenAddress, uint _keyPrice, uint _maxNumberOfKeys, string calldata _lockName, bytes12 // _salt ) public returns(address) { bytes memory data = abi.encodeWithSignature( 'initialize(address,uint256,address,uint256,uint256,string)', msg.sender, _expirationDuration, _tokenAddress, _keyPrice, _maxNumberOfKeys, _lockName ); return createUpgradeableLock(data); } /** * @notice Create upgradeable lock * This deploys a lock for a creator. It also keeps track of the deployed lock. * @param data bytes containing the call to initialize the lock template * @dev this call is passed as encoded function - for instance: * bytes memory data = abi.encodeWithSignature( * 'initialize(address,uint256,address,uint256,uint256,string)', * msg.sender, * _expirationDuration, * _tokenAddress, * _keyPrice, * _maxNumberOfKeys, * _lockName * ); * @return address of the create lock */ function createUpgradeableLock( bytes memory data ) public returns(address) { address newLock = createUpgradeableLockAtVersion(data, publicLockLatestVersion); return newLock; } /** * Create an upgradeable lock using a specific PublicLock version * @param data bytes containing the call to initialize the lock template * (refer to createUpgradeableLock for more details) * @param _lockVersion the version of the lock to use */ function createUpgradeableLockAtVersion( bytes memory data, uint16 _lockVersion ) public returns (address) { require(proxyAdminAddress != address(0), "MISSING_PROXY_ADMIN"); // get lock version address publicLockImpl = _publicLockImpls[_lockVersion]; require(publicLockImpl != address(0), 'MISSING_LOCK_TEMPLATE'); // deploy a proxy pointing to impl TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(publicLockImpl, proxyAdminAddress, data); address payable newLock = payable(address(proxy)); // assign the new Lock locks[newLock] = LockBalances({ deployed: true, totalSales: 0, yieldedDiscountTokens: 0 }); // trigger event emit NewLock(msg.sender, newLock); return newLock; } /** * @dev Upgrade a Lock template implementation * @param lockAddress the address of the lock to be upgraded * @param version the version number of the template */ function upgradeLock(address payable lockAddress, uint16 version) external returns(address) { require(proxyAdminAddress != address(0), "MISSING_PROXY_ADMIN"); // check perms require(_isLockManager(lockAddress, msg.sender) == true, "MANAGER_ONLY"); // check version IPublicLock lock = IPublicLock(lockAddress); uint16 currentVersion = lock.publicLockVersion(); require( version == currentVersion + 1, 'VERSION_TOO_HIGH'); // make our upgrade address impl = _publicLockImpls[version]; require(impl != address(0), "MISSING_TEMPLATE"); TransparentUpgradeableProxy proxy = TransparentUpgradeableProxy(lockAddress); proxyAdmin.upgrade(proxy, impl); // let's upgrade the data schema // the function is called with empty bytes as migration behaviour is set by the lock in accordance to data version lock.migrate('0x'); emit LockUpgraded(lockAddress, version); return lockAddress; } function _isLockManager(address lockAddress, address _sender) private view returns(bool isManager) { IPublicLock lock = IPublicLock(lockAddress); return lock.isLockManager(_sender); } /** * @notice [DEPRECATED] Call to this function has been removed from PublicLock > v9. * @dev [DEPRECATED] Kept for backwards compatibility */ function computeAvailableDiscountFor( address /* _purchaser */, uint /* _keyPrice */ ) public pure returns (uint discount, uint tokens) { return (0, 0); } /** * Helper to get the network mining basefee as introduced in EIP-1559 * @dev this helper can be wrapped in try/catch statement to avoid * revert in networks where EIP-1559 is not implemented */ function networkBaseFee() external view returns (uint) { return block.basefee; } /** * This function keeps track of the added GDP, as well as grants of discount tokens * to the referrer, if applicable. * The number of discount tokens granted is based on the value of the referal, * the current growth rate and the lock's discount token distribution rate * This function is invoked by a previously deployed lock only. * TODO: actually implement */ function recordKeyPurchase( uint _value, address _referrer ) public onlyFromDeployedLock() { if(_value > 0) { uint valueInETH; address tokenAddress = IPublicLock(msg.sender).tokenAddress(); if(tokenAddress != address(0) && tokenAddress != weth) { // If priced in an ERC-20 token, find the supported uniswap oracle IUniswapOracle oracle = uniswapOracles[tokenAddress]; if(address(oracle) != address(0)) { valueInETH = oracle.updateAndConsult(tokenAddress, _value, weth); } } else { // If priced in ETH (or value is 0), no conversion is required valueInETH = _value; } updateGrossNetworkProduct( valueInETH, tokenAddress, _value, msg.sender // lockAddress ); // If GNP does not overflow, the lock totalSales should be safe locks[msg.sender].totalSales += valueInETH; // Mint UDT if(_referrer != address(0)) { IUniswapOracle udtOracle = uniswapOracles[udt]; if(address(udtOracle) != address(0)) { // Get the value of 1 UDT (w/ 18 decimals) in ETH uint udtPrice = udtOracle.updateAndConsult(udt, 10 ** 18, weth); // base fee default to 100 GWEI for chains that does uint baseFee; try this.networkBaseFee() returns (uint _basefee) { // no assigned value if(_basefee == 0) { baseFee = 100; } else { baseFee = _basefee; } } catch { // block.basefee not supported baseFee = 100; } // tokensToDistribute is either == to the gas cost times 1.25 to cover the 20% dev cut uint tokensToDistribute = (estimatedGasForPurchase * baseFee) * (125 * 10 ** 18) / 100 / udtPrice; // or tokensToDistribute is capped by network GDP growth uint maxTokens = 0; if (chainId > 1) { // non mainnet: we distribute tokens using asymptotic curve between 0 and 0.5 // maxTokens = IMintableERC20(udt).balanceOf(address(this)).mul((valueInETH / grossNetworkProduct) / (2 + 2 * valueInETH / grossNetworkProduct)); maxTokens = IMintableERC20(udt).balanceOf(address(this)) * valueInETH / (2 + 2 * valueInETH / grossNetworkProduct) / grossNetworkProduct; } else { // Mainnet: we mint new token using log curve maxTokens = IMintableERC20(udt).totalSupply() * valueInETH / 2 / grossNetworkProduct; } // cap to GDP growth! if(tokensToDistribute > maxTokens) { tokensToDistribute = maxTokens; } if(tokensToDistribute > 0) { // 80% goes to the referrer, 20% to the Unlock dev - round in favor of the referrer uint devReward = tokensToDistribute * 20 / 100; if (chainId > 1) { uint balance = IMintableERC20(udt).balanceOf(address(this)); if (balance > tokensToDistribute) { // Only distribute if there are enough tokens IMintableERC20(udt).transfer(_referrer, tokensToDistribute - devReward); IMintableERC20(udt).transfer(owner(), devReward); } } else { // No distribnution IMintableERC20(udt).mint(_referrer, tokensToDistribute - devReward); IMintableERC20(udt).mint(owner(), devReward); } } } } } } /** * Update the GNP by a new value. * Emits an event to simply tracking */ function updateGrossNetworkProduct( uint _valueInETH, address _tokenAddress, uint _value, address _lock ) internal { // increase GNP grossNetworkProduct = grossNetworkProduct + _valueInETH; emit GNPChanged( grossNetworkProduct, _valueInETH, _tokenAddress, _value, _lock ); } /** * @notice [DEPRECATED] Call to this function has been removed from PublicLock > v9. * @dev [DEPRECATED] only Kept for backwards compatibility */ function recordConsumedDiscount( uint /* _discount */, uint /* _tokens */ ) public view onlyFromDeployedLock() { return; } // The version number of the current Unlock implementation on this network function unlockVersion( ) external pure returns (uint16) { return 11; } /** * @notice Allows the owner to update configuration variables */ function configUnlock( address _udt, address _weth, uint _estimatedGasForPurchase, string calldata _symbol, string calldata _URI, uint _chainId ) external onlyOwner { udt = _udt; weth = _weth; estimatedGasForPurchase = _estimatedGasForPurchase; globalTokenSymbol = _symbol; globalBaseTokenURI = _URI; chainId = _chainId; emit ConfigUnlock(_udt, _weth, _estimatedGasForPurchase, _symbol, _URI, _chainId); } /** * @notice Upgrade the PublicLock template used for future calls to `createLock`. * @dev This will initialize the template and revokeOwnership. */ function setLockTemplate( address _publicLockAddress ) external onlyOwner { // First claim the template so that no-one else could // this will revert if the template was already initialized. IPublicLock(_publicLockAddress).initialize( address(this), 0, address(0), 0, 0, '' ); IPublicLock(_publicLockAddress).renounceLockManager(); publicLockAddress = _publicLockAddress; emit SetLockTemplate(_publicLockAddress); } /** * @notice allows the owner to set the oracle address to use for value conversions * setting the _oracleAddress to address(0) removes support for the token * @dev This will also call update to ensure at least one datapoint has been recorded. */ function setOracle( address _tokenAddress, address _oracleAddress ) external onlyOwner { uniswapOracles[_tokenAddress] = IUniswapOracle(_oracleAddress); if(_oracleAddress != address(0)) { IUniswapOracle(_oracleAddress).update(_tokenAddress, weth); } } // Allows the owner to change the value tracking variables as needed. function resetTrackedValue( uint _grossNetworkProduct, uint _totalDiscountGranted ) external onlyOwner { grossNetworkProduct = _grossNetworkProduct; totalDiscountGranted = _totalDiscountGranted; emit ResetTrackedValue(_grossNetworkProduct, _totalDiscountGranted); } /** * @dev Redundant with globalBaseTokenURI() for backwards compatibility with v3 & v4 locks. */ function getGlobalBaseTokenURI() external view returns (string memory) { return globalBaseTokenURI; } /** * @dev Redundant with globalTokenSymbol() for backwards compatibility with v3 & v4 locks. */ function getGlobalTokenSymbol() external view returns (string memory) { return globalTokenSymbol; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol) pragma solidity ^0.8.0; import "../ERC1967/ERC1967Proxy.sol"; /** * @dev This contract implements a proxy that is upgradeable by an admin. * * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector * clashing], which can potentially be used in an attack, this contract uses the * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two * things that go hand in hand: * * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if * that call matches one of the admin functions exposed by the proxy itself. * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the * implementation. If the admin tries to call a function on the implementation it will fail with an error that says * "admin cannot fallback to proxy target". * * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due * to sudden errors when trying to call a function from the proxy implementation. * * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. */ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. */ constructor( address _logic, address admin_, bytes memory _data ) payable ERC1967Proxy(_logic, _data) { assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); _changeAdmin(admin_); } /** * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { _; } else { _fallback(); } } /** * @dev Returns the current admin. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function admin() external ifAdmin returns (address admin_) { admin_ = _getAdmin(); } /** * @dev Returns the current implementation. * * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ function implementation() external ifAdmin returns (address implementation_) { implementation_ = _implementation(); } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. * * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. */ function changeAdmin(address newAdmin) external virtual ifAdmin { _changeAdmin(newAdmin); } /** * @dev Upgrade the implementation of the proxy. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}. */ function upgradeTo(address newImplementation) external ifAdmin { _upgradeToAndCall(newImplementation, bytes(""), false); } /** * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the * proxied contract. * * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. */ function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin { _upgradeToAndCall(newImplementation, data, true); } /** * @dev Returns the current admin. */ function _admin() internal view virtual returns (address) { return _getAdmin(); } /** * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. */ function _beforeFallback() internal virtual override { require(msg.sender != _getAdmin(), "TransparentUpgradeableProxy: admin cannot fallback to proxy target"); super._beforeFallback(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol) pragma solidity ^0.8.0; import "./TransparentUpgradeableProxy.sol"; import "../../access/Ownable.sol"; /** * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. */ contract ProxyAdmin is Ownable { /** * @dev Returns the current implementation of `proxy`. * * Requirements: * * - This contract must be the admin of `proxy`. */ function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) { // We need to manually run the static call since the getter cannot be flagged as view // bytes4(keccak256("implementation()")) == 0x5c60da1b (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); require(success); return abi.decode(returndata, (address)); } /** * @dev Returns the current admin of `proxy`. * * Requirements: * * - This contract must be the admin of `proxy`. */ function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) { // We need to manually run the static call since the getter cannot be flagged as view // bytes4(keccak256("admin()")) == 0xf851a440 (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); require(success); return abi.decode(returndata, (address)); } /** * @dev Changes the admin of `proxy` to `newAdmin`. * * Requirements: * * - This contract must be the current admin of `proxy`. */ function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner { proxy.changeAdmin(newAdmin); } /** * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner { proxy.upgradeTo(implementation); } /** * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See * {TransparentUpgradeableProxy-upgradeToAndCall}. * * Requirements: * * - This contract must be the admin of `proxy`. */ function upgradeAndCall( TransparentUpgradeableProxy proxy, address implementation, bytes memory data ) public payable virtual onlyOwner { proxy.upgradeToAndCall{value: msg.value}(implementation, data); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.0; interface IUniswapOracle { function PERIOD() external returns (uint); function factory() external returns (address); function update( address _tokenIn, address _tokenOut ) external; function consult( address _tokenIn, uint _amountIn, address _tokenOut ) external view returns (uint _amountOut); function updateAndConsult( address _tokenIn, uint _amountIn, address _tokenOut ) external returns (uint _amountOut); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.3.2 (access/Ownable.sol) pragma solidity ^0.8.0; import './UnlockInitializable.sol'; import './UnlockContextUpgradeable.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. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be aplied to your functions to restrict their use to * the owner. * * This contract was originally part of openzeppelin/contracts-ethereum-package * but had to be included (instead of using the one in openzeppelin/contracts-upgradeable ) * because the ______gap array length was 49 instead of 50 */ abstract contract UnlockOwnable is UnlockInitializable, UnlockContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __initializeOwnable(address sender) public initializer { _owner = sender; emit OwnershipTransferred(address(0), _owner); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "ONLY_OWNER"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _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 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 onlyOwner { require(newOwner != address(0), "INVALID_OWNER"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } uint256[50] private ______gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol) pragma solidity ^0.8.0; import '@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol'; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * 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 initialize the implementation contract, you can either invoke the * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() initializer {} * ``` * ==== */ abstract contract UnlockInitializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { // If the contract is initializing we ignore whether initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require(initializing ? _isConstructor() : !initialized, "ALREADY_INITIALIZED"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializing() { require(initializing, "NOT_INITIALIZING"); _; } function _isConstructor() private view returns (bool) { return !AddressUpgradeable.isContract(address(this)); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.17 <0.9.0; pragma experimental ABIEncoderV2; /** * @title The PublicLock Interface * @author Nick Furfaro (unlock-protocol.com) */ interface IPublicLock { // See indentationissue description here: // https://github.com/duaraghav8/Ethlint/issues/268 // solium-disable indentation /// Functions function initialize( address _lockCreator, uint _expirationDuration, address _tokenAddress, uint _keyPrice, uint _maxNumberOfKeys, string calldata _lockName ) external; /** * @notice Allow the contract to accept tips in ETH sent directly to the contract. * @dev This is okay to use even if the lock is priced in ERC-20 tokens */ // receive() external payable; // roles function DEFAULT_ADMIN_ROLE() external pure returns (bytes32); function KEY_GRANTER_ROLE() external pure returns (bytes32); function LOCK_MANAGER_ROLE() external pure returns (bytes32); /** * @notice The version number of the current implementation on this network. * @return The current version number. */ function publicLockVersion() external pure returns (uint16); /** * @dev Called by a lock manager or beneficiary to withdraw all funds from the lock and send them to the `beneficiary`. * @dev Throws if called by other than a lock manager or beneficiary * @param _tokenAddress specifies the token address to withdraw or 0 for ETH. This is usually * the same as `tokenAddress` in MixinFunds. * @param _amount specifies the max amount to withdraw, which may be reduced when * considering the available balance. Set to 0 or MAX_UINT to withdraw everything. * -- however be wary of draining funds as it breaks the `cancelAndRefund` and `expireAndRefundFor` * use cases. */ function withdraw( address _tokenAddress, uint _amount ) external; /** * @notice An ERC-20 style approval, allowing the spender to transfer funds directly from this lock. */ function approveBeneficiary( address _spender, uint _amount ) external returns (bool); /** * A function which lets a Lock manager of the lock to change the price for future purchases. * @dev Throws if called by other than a Lock manager * @dev Throws if lock has been disabled * @dev Throws if _tokenAddress is not a valid token * @param _keyPrice The new price to set for keys * @param _tokenAddress The address of the erc20 token to use for pricing the keys, * or 0 to use ETH */ function updateKeyPricing( uint _keyPrice, address _tokenAddress ) external; /** * A function to change the default duration of each key in the lock * @notice keys previously bought are unaffected by this change (i.e. * existing keys timestamps are not recalculated/updated) * @param _newExpirationDuration the new amount of time for each key purchased * or type(uint).max for a non-expiring key */ function setExpirationDuration(uint _newExpirationDuration) external; /** * A function which lets a Lock manager update the beneficiary account, * which receives funds on withdrawal. * @dev Throws if called by other than a Lock manager or beneficiary * @dev Throws if _beneficiary is address(0) * @param _beneficiary The new address to set as the beneficiary */ function updateBeneficiary( address _beneficiary ) external; /** * Checks if the user has a non-expired key. * @param _user The address of the key owner */ function getHasValidKey( address _user ) external view returns (bool); /** * @dev Returns the key's ExpirationTimestamp field for a given owner. * @param _tokenId the id of the key * @dev Returns 0 if the owner has never owned a key for this lock */ function keyExpirationTimestampFor( uint _tokenId ) external view returns (uint timestamp); /** * Public function which returns the total number of unique owners (both expired * and valid). This may be larger than totalSupply. */ function numberOfOwners() external view returns (uint); /** * Allows a Lock manager to assign a descriptive name for this Lock. * @param _lockName The new name for the lock * @dev Throws if called by other than a Lock manager */ function updateLockName( string calldata _lockName ) external; /** * Allows a Lock manager to assign a Symbol for this Lock. * @param _lockSymbol The new Symbol for the lock * @dev Throws if called by other than a Lock manager */ function updateLockSymbol( string calldata _lockSymbol ) external; /** * @dev Gets the token symbol * @return string representing the token symbol */ function symbol() external view returns(string memory); /** * Allows a Lock manager to update the baseTokenURI for this Lock. * @dev Throws if called by other than a Lock manager * @param _baseTokenURI String representing the base of the URI for this lock. */ function setBaseTokenURI( string calldata _baseTokenURI ) external; /** @notice A distinct Uniform Resource Identifier (URI) for a given asset. * @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC * 3986. The URI may point to a JSON file that conforms to the "ERC721 * Metadata JSON Schema". * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md * @param _tokenId The tokenID we're inquiring about * @return String representing the URI for the requested token */ function tokenURI( uint256 _tokenId ) external view returns(string memory); /** * @notice Allows a Lock manager to add or remove an event hook */ function setEventHooks( address _onKeyPurchaseHook, address _onKeyCancelHook, address _onValidKeyHook, address _onTokenURIHook ) external; /** * Allows a Lock manager to give a collection of users a key with no charge. * Each key may be assigned a different expiration date. * @dev Throws if called by other than a Lock manager * @param _recipients An array of receiving addresses * @param _expirationTimestamps An array of expiration Timestamps for the keys being granted */ function grantKeys( address[] calldata _recipients, uint[] calldata _expirationTimestamps, address[] calldata _keyManagers ) external; /** * @dev Purchase function * @param _values array of tokens amount to pay for this purchase >= the current keyPrice - any applicable discount * (_values is ignored when using ETH) * @param _recipients array of addresses of the recipients of the purchased key * @param _referrers array of addresses of the users making the referral * @param _keyManagers optional array of addresses to grant managing rights to a specific address on creation * @param _data array of arbitrary data populated by the front-end which initiated the sale * @notice when called for an existing and non-expired key, the `_keyManager` param will be ignored * @dev Setting _value to keyPrice exactly doubles as a security feature. That way if the lock owner increases the * price while my transaction is pending I can't be charged more than I expected (only applicable to ERC-20 when more * than keyPrice is approved for spending). */ function purchase( uint256[] calldata _values, address[] calldata _recipients, address[] calldata _referrers, address[] calldata _keyManagers, bytes[] calldata _data ) external payable; /** * @dev Extend function * @param _value the number of tokens to pay for this purchase >= the current keyPrice - any applicable discount * (_value is ignored when using ETH) * @param _tokenId the id of the key to extend * @param _referrer address of the user making the referral * @param _data arbitrary data populated by the front-end which initiated the sale * @dev Throws if lock is disabled or key does not exist for _recipient. Throws if _recipient == address(0). */ function extend( uint _value, uint _tokenId, address _referrer, bytes calldata _data ) external payable; /** * Merge existing keys * @param _tokenIdFrom the id of the token to substract time from * @param _tokenIdTo the id of the destination token to add time * @param _amount the amount of time to transfer (in seconds) */ function mergeKeys(uint _tokenIdFrom, uint _tokenIdTo, uint _amount) external; /** * Deactivate an existing key * @param _tokenId the id of token to burn * @notice the key will be expired and ownership records will be destroyed */ function burn(uint _tokenId) external; /** * @param _gasRefundValue price in wei or token in smallest price unit * @dev Set the value to be refunded to the sender on purchase */ function setGasRefundValue(uint256 _gasRefundValue) external; /** * _gasRefundValue price in wei or token in smallest price unit * @dev Returns the value/rpice to be refunded to the sender on purchase */ function gasRefundValue() external view returns (uint256 _gasRefundValue); /** * @notice returns the minimum price paid for a purchase with these params. * @dev this considers any discount from Unlock or the OnKeyPurchase hook. */ function purchasePriceFor( address _recipient, address _referrer, bytes calldata _data ) external view returns (uint); /** * Allow a Lock manager to change the transfer fee. * @dev Throws if called by other than a Lock manager * @param _transferFeeBasisPoints The new transfer fee in basis-points(bps). * Ex: 200 bps = 2% */ function updateTransferFee( uint _transferFeeBasisPoints ) external; /** * Determines how much of a fee would need to be paid in order to * transfer to another account. This is pro-rated so the fee goes * down overtime. * @dev Throws if _tokenId does not have a valid key * @param _tokenId The id of the key check the transfer fee for. * @param _time The amount of time to calculate the fee for. * @return The transfer fee in seconds. */ function getTransferFee( uint _tokenId, uint _time ) external view returns (uint); /** * @dev Invoked by a Lock manager to expire the user's key * and perform a refund and cancellation of the key * @param _tokenId The key id we wish to refund to * @param _amount The amount to refund to the key-owner * @dev Throws if called by other than a Lock manager * @dev Throws if _keyOwner does not have a valid key */ function expireAndRefundFor( uint _tokenId, uint _amount ) external; /** * @dev allows the key manager to expire a given tokenId * and send a refund to the keyOwner based on the amount of time remaining. * @param _tokenId The id of the key to cancel. */ function cancelAndRefund(uint _tokenId) external; /** * Allow a Lock manager to change the refund penalty. * @dev Throws if called by other than a Lock manager * @param _freeTrialLength The new duration of free trials for this lock * @param _refundPenaltyBasisPoints The new refund penaly in basis-points(bps) */ function updateRefundPenalty( uint _freeTrialLength, uint _refundPenaltyBasisPoints ) external; /** * @dev Determines how much of a refund a key owner would receive if they issued * @param _keyOwner The key owner to get the refund value for. * a cancelAndRefund block.timestamp. * Note that due to the time required to mine a tx, the actual refund amount will be lower * than what the user reads from this call. */ function getCancelAndRefundValue( address _keyOwner ) external view returns (uint refund); function addKeyGranter(address account) external; function addLockManager(address account) external; function isKeyGranter(address account) external view returns (bool); function isLockManager(address account) external view returns (bool); function onKeyPurchaseHook() external view returns(address); function onKeyCancelHook() external view returns(address); function onValidKeyHook() external view returns(bool); function onTokenURIHook() external view returns(string memory); function revokeKeyGranter(address _granter) external; function renounceLockManager() external; /** * @dev Change the maximum number of keys the lock can edit * @param _maxNumberOfKeys uint the maximum number of keys */ function setMaxNumberOfKeys (uint _maxNumberOfKeys) external; /** * Set the maximum number of keys a specific address can use * @param _maxKeysPerAddress the maximum amount of key a user can own */ function setMaxKeysPerAddress (uint _maxKeysPerAddress) external; /** * @return the maximum number of key allowed for a single address */ function maxKeysPerAddress() external view returns (uint); ///=================================================================== /// Auto-generated getter functions from public state variables function beneficiary() external view returns (address ); function expirationDuration() external view returns (uint256 ); function freeTrialLength() external view returns (uint256 ); function keyPrice() external view returns (uint256 ); function maxNumberOfKeys() external view returns (uint256 ); function refundPenaltyBasisPoints() external view returns (uint256 ); function tokenAddress() external view returns (address ); function transferFeeBasisPoints() external view returns (uint256 ); function unlockProtocol() external view returns (address ); function keyManagerOf(uint) external view returns (address ); ///=================================================================== /** * @notice Allows the key owner to safely share their key (parent key) by * transferring a portion of the remaining time to a new key (child key). * @dev Throws if key is not valid. * @dev Throws if `_to` is the zero address * @param _to The recipient of the shared key * @param _tokenId the key to share * @param _timeShared The amount of time shared * checks if `_to` is a smart contract (code size > 0). If so, it calls * `onERC721Received` on `_to` and throws if the return value is not * `bytes4(keccak256('onERC721Received(address,address,uint,bytes)'))`. * @dev Emit Transfer event */ function shareKey( address _to, uint _tokenId, uint _timeShared ) external; /** * @notice Update transfer and cancel rights for a given key * @param _tokenId The id of the key to assign rights for * @param _keyManager The address to assign the rights to for the given key */ function setKeyManagerOf( uint _tokenId, address _keyManager ) external; /** * Check if a certain key is valid * @param _tokenId the id of the key to check validity * @notice this makes use of the onValidKeyHook if it is set */ function isValidKey( uint _tokenId ) external view returns (bool); /// @notice A descriptive name for a collection of NFTs in this contract function name() external view returns (string memory _name); ///=================================================================== /// From ERC165.sol function supportsInterface(bytes4 interfaceId) external view returns (bool); ///=================================================================== /// From ERC-721 /** * @dev Returns the number of NFTs in `owner`'s account. */ function balanceOf(address _owner) external view returns (uint256 balance); /** * @dev Returns the owner of the NFT specified by `tokenId`. */ function ownerOf(uint256 tokenId) external view returns (address _owner); /** * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to * another (`to`). * * Requirements: * - `from`, `to` cannot be zero. * - `tokenId` must be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this * NFT by either {approve} or {setApprovalForAll}. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to * another (`to`). * * Requirements: * - If the caller is not `from`, it must be approved to move this NFT by * either {approve} or {setApprovalForAll}. */ function transferFrom(address from, address to, uint256 tokenId) external; function approve(address to, uint256 tokenId) external; /** * @notice Get the approved address for a single NFT * @dev Throws if `_tokenId` is not a valid NFT. * @param _tokenId The NFT to find the approved address for * @return operator The approved address for this NFT, or the zero address if there is none */ function getApproved(uint256 _tokenId) external view returns (address operator); /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf * @param _operator operator address to set the approval * @param _approved representing the status of the approval to be set * @notice disabled when transfers are disabled */ function setApprovalForAll(address _operator, bool _approved) external; /** * @dev Tells whether an operator is approved by a given keyManager * @param _owner owner address which you want to query the approval of * @param _operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll(address _owner, address _operator) external view returns (bool); function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; function totalSupply() external view returns (uint256); function tokenOfOwnerByIndex(address _owner, uint256 index) external view returns (uint256 tokenId); function tokenByIndex(uint256 index) external view returns (uint256); /** * Innherited from Open Zeppelin AccessControl.sol */ function getRoleAdmin(bytes32 role) external view returns (bytes32); function grantRole(bytes32 role, address account) external; function revokeRole(bytes32 role, address account) external; function renounceRole(bytes32 role, address account) external; function hasRole(bytes32 role, address account) external view returns (bool); /** * @notice An ERC-20 style transfer. * @param _value sends a token with _value * expirationDuration (the amount of time remaining on a standard purchase). * @dev The typical use case would be to call this with _value 1, which is on par with calling `transferFrom`. If the user * has more than `expirationDuration` time remaining this may use the `shareKey` function to send some but not all of the token. */ function transfer( address _to, uint _value ) external returns (bool success); /** `owner()` is provided as an helper to mimick the `Ownable` contract ABI. * The `Ownable` logic is used by many 3rd party services to determine * contract ownership - e.g. who is allowed to edit metadata on Opensea. * * @notice This logic is NOT used internally by the Unlock Protocol and is made * available only as a convenience helper. */ function owner() external view returns (address); function setOwner(address account) external; function isOwner(address account) external returns (bool); /** * Migrate data from the previous single owner => key mapping to * the new data structure w multiple tokens. * @param _calldata an ABI-encoded representation of the params (v10: the number of records to migrate as `uint`) * @dev when all record schemas are sucessfully upgraded, this function will update the `schemaVersion` * variable to the latest/current lock version */ function migrate(bytes calldata _calldata) external; /** * Returns the version number of the data schema currently used by the lock * @notice if this is different from `publicLockVersion`, then the ability to purchase, grant * or extend keys is disabled. * @dev will return 0 if no ;igration has ever been run */ function schemaVersion() external view returns (uint); /** * Set the schema version to the latest * @notice only lock manager call call this */ function updateSchemaVersion() external; /** * Renew a given token * @notice only works for non-free, expiring, ERC20 locks * @param _tokenId the ID fo the token to renew * @param _referrer the address of the person to be granted UDT */ function renewMembershipFor( uint _tokenId, address _referrer ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.17 <0.9.0; interface IMintableERC20 { function mint(address account, uint256 amount) external returns (bool); function transfer(address recipient, uint256 amount) external returns (bool); function totalSupply() external returns (uint); function balanceOf(address account) external returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol) pragma solidity ^0.8.0; import "../Proxy.sol"; import "./ERC1967Upgrade.sol"; /** * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an * implementation address that can be changed. This address is stored in storage in the location specified by * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the * implementation behind the proxy. */ contract ERC1967Proxy is Proxy, ERC1967Upgrade { /** * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`. * * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded * function call, and allows initializating the storage of the proxy like a Solidity constructor. */ constructor(address _logic, bytes memory _data) payable { assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); _upgradeToAndCall(_logic, _data, false); } /** * @dev Returns the current implementation address. */ function _implementation() internal view virtual override returns (address impl) { return ERC1967Upgrade._getImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/Proxy.sol) pragma solidity ^0.8.0; /** * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to * be specified by overriding the virtual {_implementation} function. * * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a * different contract through the {_delegate} function. * * The success and return data of the delegated call will be returned back to the caller of the proxy. */ abstract contract Proxy { /** * @dev Delegates the current call to `implementation`. * * This function does not return to its internall call site, it will return directly to the external caller. */ function _delegate(address implementation) internal virtual { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } /** * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function * and {_fallback} should delegate. */ function _implementation() internal view virtual returns (address); /** * @dev Delegates the current call to the address returned by `_implementation()`. * * This function does not return to its internall call site, it will return directly to the external caller. */ function _fallback() internal virtual { _beforeFallback(); _delegate(_implementation()); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other * function in the contract matches the call data. */ fallback() external payable virtual { _fallback(); } /** * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data * is empty. */ receive() external payable virtual { _fallback(); } /** * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback` * call, or as part of the Solidity `fallback` or `receive` functions. * * If overriden should call `super._beforeFallback()`. */ function _beforeFallback() internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeacon.sol"; import "../../utils/Address.sol"; import "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ * * @custom:oz-upgrades-unsafe-allow delegatecall */ abstract contract ERC1967Upgrade { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall( address newImplementation, bytes memory data, bool forceCall ) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallSecure( address newImplementation, bytes memory data, bool forceCall ) internal { address oldImplementation = _getImplementation(); // Initial upgrade and setup call _setImplementation(newImplementation); if (data.length > 0 || forceCall) { Address.functionDelegateCall(newImplementation, data); } // Perform rollback test if not already in progress StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT); if (!rollbackTesting.value) { // Trigger rollback using upgradeTo from the new implementation rollbackTesting.value = true; Address.functionDelegateCall( newImplementation, abi.encodeWithSignature("upgradeTo(address)", oldImplementation) ); rollbackTesting.value = false; // Check rollback was effective require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades"); // Finally reset to the new implementation and log the upgrade _upgradeTo(newImplementation); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Emitted when the beacon is upgraded. */ event BeaconUpgraded(address indexed beacon); /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( Address.isContract(IBeacon(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall( address newBeacon, bytes memory data, bool forceCall ) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol) pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ``` * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._ */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly { r.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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 Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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: 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: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "./UnlockInitializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract UnlockContextUpgradeable is UnlockInitializable { function __Context_init() internal onlyInitializing { __Context_init_unchained(); } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private ______gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "optimizer": { "enabled": true, "runs": 80 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"udt","type":"address"},{"indexed":false,"internalType":"address","name":"weth","type":"address"},{"indexed":false,"internalType":"uint256","name":"estimatedGasForPurchase","type":"uint256"},{"indexed":false,"internalType":"string","name":"globalTokenSymbol","type":"string"},{"indexed":false,"internalType":"string","name":"globalTokenURI","type":"string"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ConfigUnlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"grossNetworkProduct","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_valueInETH","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"address","name":"lockAddress","type":"address"}],"name":"GNPChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lockAddress","type":"address"},{"indexed":false,"internalType":"uint16","name":"version","type":"uint16"}],"name":"LockUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lockOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newLockAddress","type":"address"}],"name":"NewLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"grossNetworkProduct","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalDiscountGranted","type":"uint256"}],"name":"ResetTrackedValue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"publicLockAddress","type":"address"}],"name":"SetLockTemplate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"impl","type":"address"},{"indexed":true,"internalType":"uint16","name":"version","type":"uint16"}],"name":"UnlockTemplateAdded","type":"event"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"__initializeOwnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"impl","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"}],"name":"addLockTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"computeAvailableDiscountFor","outputs":[{"internalType":"uint256","name":"discount","type":"uint256"},{"internalType":"uint256","name":"tokens","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_udt","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"uint256","name":"_estimatedGasForPurchase","type":"uint256"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_URI","type":"string"},{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"configUnlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_expirationDuration","type":"uint256"},{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_keyPrice","type":"uint256"},{"internalType":"uint256","name":"_maxNumberOfKeys","type":"uint256"},{"internalType":"string","name":"_lockName","type":"string"},{"internalType":"bytes12","name":"","type":"bytes12"}],"name":"createLock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"createUpgradeableLock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint16","name":"_lockVersion","type":"uint16"}],"name":"createUpgradeableLockAtVersion","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"estimatedGasForPurchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalBaseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalTokenSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalBaseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalTokenSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"grossNetworkProduct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_unlockOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeProxyAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"locks","outputs":[{"internalType":"bool","name":"deployed","type":"bool"},{"internalType":"uint256","name":"totalSales","type":"uint256"},{"internalType":"uint256","name":"yieldedDiscountTokens","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"networkBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxyAdminAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicLockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"publicLockImpls","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicLockLatestVersion","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_impl","type":"address"}],"name":"publicLockVersions","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"recordConsumedDiscount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"recordKeyPurchase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_grossNetworkProduct","type":"uint256"},{"internalType":"uint256","name":"_totalDiscountGranted","type":"uint256"}],"name":"resetTrackedValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_publicLockAddress","type":"address"}],"name":"setLockTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_oracleAddress","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalDiscountGranted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"udt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"uniswapOracles","outputs":[{"internalType":"contract IUniswapOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockVersion","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address payable","name":"lockAddress","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"}],"name":"upgradeLock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50613ccc806100206000396000f3fe60806040523480156200001157600080fd5b50600436106200021d5760003560e01c80638da5cb5b1162000127578063c4d66de811620000b6578063c4d66de81462000503578063c7d7d0c9146200051a578063caeee3a31462000524578063ccf54648146200053b578063cd93b5321462000552578063cec410521462000561578063d6e9e803146200056b578063ef67fde61462000575578063f2fde38b146200058c578063f832899114620005a357600080fd5b80638da5cb5b146200046c5780638f32d59b146200047e578063939d9f1f1462000499578063963a947814620004b05780639a8a059214620004c7578063a082eb0e14620004d1578063a998e9fb14620004db578063b0ca0c8314620004e5578063ba5ea0d514620004fc57600080fd5b8063487a8a7611620001b0578063487a8a7614620003365780635979e755146200034d5780635c38eb3a14620003615780635de9a1371462000378578063666018a514620003cc5780636bced5a214620003fc578063715018a61462000428578063743bbc2f14620004325780637d8fb641146200044b5780637ff94bb2146200046257600080fd5b80630cb175e3146200022257806325772ad91462000253578063262d0a85146200029757806335a750de14620002ba5780633652466314620002d35780633fc8cef314620002ec5780634220bd46146200030057806342d9210614620003085780634452c2b2146200031f575b600080fd5b620002396200023336600462001ffe565b620005b7565b604080519283526020830191909152015b60405180910390f35b620002836200026436600462001e9d565b6001600160a01b031660009081526073602052604090205461ffff1690565b60405161ffff90911681526020016200024a565b606e54620002ab906001600160a01b031681565b6040516200024a91906200228d565b620002c4620005c2565b6040516200024a9190620023b5565b620002ea620002e4366004620021f1565b6200065c565b005b606d54620002ab906001600160a01b031681565b600b62000283565b620002ab6200031936600462002157565b6200069b565b620002ab6200033036600462002051565b62000701565b620002ab6200034736600462002089565b62000721565b607154620002ab906001600160a01b031681565b620002ea6200037236600462001f1b565b6200088e565b620003ae6200038936600462001e9d565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6040805193151584526020840192909252908201526060016200024a565b620002ab620003dd366004620020d5565b61ffff166000908152607460205260409020546001600160a01b031690565b620002ab6200040d36600462001e9d565b606c602052600090815260409020546001600160a01b031681565b620002ea62000957565b6200043c606f5481565b6040519081526020016200024a565b620002ea6200045c36600462001f4e565b6200098e565b620002c462000a61565b6033546001600160a01b0316620002ab565b6200048862000a72565b60405190151581526020016200024a565b620002ea620004aa3660046200212f565b62000a83565b620002ea620004c1366004620021f1565b620012ee565b6200043c60705481565b6200043c60675481565b620002c46200135e565b620002ea620004f636600462001e9d565b620013f4565b486200043c565b620002ea6200051436600462001e9d565b620014b6565b620002ea62001545565b620002ea6200053536600462001edd565b620015c9565b620002ab6200054c36600462001edd565b62001697565b607554620002839061ffff1681565b620002c462001970565b6200043c60665481565b620002ea6200058636600462001e9d565b6200197f565b620002ea6200059d36600462001e9d565b62001ada565b606b54620002ab906001600160a01b031681565b6000805b9250929050565b6060606a8054620005d3906200250f565b80601f016020809104026020016040519081016040528092919081815260200182805462000601906200250f565b8015620006525780601f10620006265761010080835404028352916020019162000652565b820191906000526020600020905b8154815290600101906020018083116200063457829003601f168201915b5050505050905090565b3360009081526068602052604090205460ff16620006975760405162461bcd60e51b81526004016200068e90620023f7565b60405180910390fd5b5050565b60008033898989898989604051602401620006bd979695949392919062002375565b60408051601f198184030181529190526020810180516001600160e01b0316636eadde4360e01b1790529050620006f48162000701565b9998505050505050505050565b60755460009081906200071a90849061ffff1662000721565b9392505050565b6071546000906001600160a01b03166200074f5760405162461bcd60e51b81526004016200068e906200241b565b61ffff82166000908152607460205260409020546001600160a01b031680620007b35760405162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b60448201526064016200068e565b60715460405160009183916001600160a01b03909116908790620007d79062001d03565b620007e593929190620022a1565b604051809103906000f08015801562000802573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350839233917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a395945050505050565b6200089862000a72565b620008b75760405162461bcd60e51b81526004016200068e9062002448565b6001600160a01b038281166000908152606c6020526040902080546001600160a01b0319169183169182179055156200069757606d5460405163c640752d60e01b81526001600160a01b03848116600483015291821660248201529082169063c640752d90604401600060405180830381600087803b1580156200093a57600080fd5b505af11580156200094f573d6000803e3d6000fd5b505050505050565b6200096162000a72565b620009805760405162461bcd60e51b81526004016200068e9062002448565b6200098c600062001b51565b565b6200099862000a72565b620009b75760405162461bcd60e51b81526004016200068e9062002448565b606e80546001600160a01b03808b166001600160a01b031992831617909255606d8054928a1692909116919091179055606f869055620009fa606a868662001d11565b5062000a096069848462001d11565b5060708190556040517fa14230a1687e9bb8cdc0f3931d27c3a806e88c1c2235ba7756d6911feb35be679062000a4f908a908a908a908a908a908a908a908a90620022d8565b60405180910390a15050505050505050565b606060698054620005d3906200250f565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff1662000ab55760405162461bcd60e51b81526004016200068e90620023f7565b81156200069757600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b15801562000af957600080fd5b505afa15801562000b0e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b34919062001ebd565b90506001600160a01b0381161580159062000b5d5750606d546001600160a01b03828116911614155b1562000c1c576001600160a01b038082166000908152606c602052604090205416801562000c1557606d5460405163c1e553e760e01b81526001600160a01b038084169263c1e553e79262000bbc9287928b9291169060040162002339565b602060405180830381600087803b15801562000bd757600080fd5b505af115801562000bec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c12919062002115565b92505b5062000c20565b8391505b62000c2e8282863362001ba3565b336000908152606860205260408120600101805484929062000c5290849062002495565b90915550506001600160a01b03831615620012e857606e546001600160a01b039081166000908152606c6020526040902054168015620012e657606e54606d5460405163c1e553e760e01b81526000926001600160a01b038086169363c1e553e79362000cd193831692670de0b6b3a764000092169060040162002339565b602060405180830381600087803b15801562000cec57600080fd5b505af115801562000d01573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d27919062002115565b90506000306001600160a01b031663ba5ea0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801562000d6557600080fd5b505afa92505050801562000d98575060408051601f3d908101601f1916820190925262000d959181019062002115565b60015b62000da65750606462000dbc565b8062000db6576064915062000dba565b8091505b505b600082606483606f5462000dd19190620024d3565b62000de6906806c6b935b8bbd40000620024d3565b62000df29190620024b0565b62000dfe9190620024b0565b905060006001607054111562000eec576066548062000e1f896002620024d3565b62000e2b9190620024b0565b62000e3890600262002495565b606e546040516370a0823160e01b81528a916001600160a01b0316906370a082319062000e6a9030906004016200228d565b602060405180830381600087803b15801562000e8557600080fd5b505af115801562000e9a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ec0919062002115565b62000ecc9190620024d3565b62000ed89190620024b0565b62000ee49190620024b0565b905062000fa5565b606654600288606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801562000f4357600080fd5b505af115801562000f58573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f7e919062002115565b62000f8a9190620024d3565b62000f969190620024b0565b62000fa29190620024b0565b90505b8082111562000fb2578091505b8115620012e1576000606462000fca846014620024d3565b62000fd69190620024b0565b905060016070541115620011af57606e546040516370a0823160e01b81526000916001600160a01b0316906370a0823190620010179030906004016200228d565b602060405180830381600087803b1580156200103257600080fd5b505af115801562001047573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200106d919062002115565b905083811115620011a857606e546001600160a01b031663a9059cbb8b620010968588620024f5565b6040518363ffffffff1660e01b8152600401620010b59291906200235c565b602060405180830381600087803b158015620010d057600080fd5b505af1158015620010e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200110b91906200202d565b50606e546001600160a01b031663a9059cbb620011306033546001600160a01b031690565b846040518363ffffffff1660e01b8152600401620011509291906200235c565b602060405180830381600087803b1580156200116b57600080fd5b505af115801562001180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011a691906200202d565b505b50620012df565b606e546001600160a01b03166340c10f198a620011cd8487620024f5565b6040518363ffffffff1660e01b8152600401620011ec9291906200235c565b602060405180830381600087803b1580156200120757600080fd5b505af11580156200121c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200124291906200202d565b50606e546001600160a01b03166340c10f19620012676033546001600160a01b031690565b836040518363ffffffff1660e01b8152600401620012879291906200235c565b602060405180830381600087803b158015620012a257600080fd5b505af1158015620012b7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012dd91906200202d565b505b505b505050505b505b50505050565b620012f862000a72565b620013175760405162461bcd60e51b81526004016200068e9062002448565b6066829055606781905560408051838152602081018390527f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb910160405180910390a15050565b606980546200136d906200250f565b80601f01602080910402602001604051908101604052809291908181526020018280546200139b906200250f565b8015620013ec5780601f10620013c057610100808354040283529160200191620013ec565b820191906000526020600020905b815481529060010190602001808311620013ce57829003601f168201915b505050505081565b600054610100900460ff16620014115760005460ff161562001415565b303b155b620014345760405162461bcd60e51b81526004016200068e90620023ca565b600054610100900460ff1615801562001457576000805461ffff19166101011790555b603380546001600160a01b0319166001600160a01b0384169081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801562000697576000805461ff00191690555050565b600054610100900460ff16620014d35760005460ff1615620014d7565b303b155b620014f65760405162461bcd60e51b81526004016200068e90620023ca565b600054610100900460ff1615801562001519576000805461ffff19166101011790555b6200152482620013f4565b6200152e62001c14565b50801562000697576000805461ff00191690555050565b6200154f62000a72565b6200156e5760405162461bcd60e51b81526004016200068e9062002448565b6071546001600160a01b031615620015bc5760405162461bcd60e51b815260206004820152601060248201526f1053149150511657d111541313d6515160821b60448201526064016200068e565b620015c662001c14565b50565b620015d362000a72565b620015f25760405162461bcd60e51b81526004016200068e9062002448565b6001600160a01b0382166000818152607360209081526040808320805461ffff191661ffff8781169182179092558085526074909352922080546001600160a01b03191690931790925560755416101562001659576075805461ffff191661ffff83161790555b60405161ffff8216906001600160a01b038416907fd36d021c4aa145e30eadc73e34284101030d688b9eb9413a4dc3af40ab1d474890600090a35050565b6071546000906001600160a01b0316620016c55760405162461bcd60e51b81526004016200068e906200241b565b620016d1833362001c74565b1515600114620017135760405162461bcd60e51b815260206004820152600c60248201526b4d414e414745525f4f4e4c5960a01b60448201526064016200068e565b60008390506000816001600160a01b031663d1bbd49c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200175457600080fd5b505afa15801562001769573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200178f9190620020f5565b90506200179e8160016200246c565b61ffff168461ffff1614620017e95760405162461bcd60e51b815260206004820152601060248201526f0ac8aa4a6929e9cbea89e9ebe90928e960831b60448201526064016200068e565b61ffff84166000908152607460205260409020546001600160a01b031680620018485760405162461bcd60e51b815260206004820152601060248201526f4d495353494e475f54454d504c41544560801b60448201526064016200068e565b60725460405163266a23b160e21b81526001600160a01b0380891660048301528381166024830152889216906399a88ec490604401600060405180830381600087803b1580156200189857600080fd5b505af1158015620018ad573d6000803e3d6000fd5b5050604051638932a90d60e01b8152602060048201526002602482015261060f60f31b60448201526001600160a01b0387169250638932a90d9150606401600060405180830381600087803b1580156200190657600080fd5b505af11580156200191b573d6000803e3d6000fd5b5050604080516001600160a01b038b16815261ffff8a1660208201527f5e7b70a9e6f0b4c7cf2657cf563ce85eed3aebb7731396118d01a195d218fd5e935001905060405180910390a1509495945050505050565b606a80546200136d906200250f565b6200198962000a72565b620019a85760405162461bcd60e51b81526004016200068e9062002448565b604051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c48201526001600160a01b03821690636eadde439060e401600060405180830381600087803b15801562001a1457600080fd5b505af115801562001a29573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801562001a6957600080fd5b505af115801562001a7e573d6000803e3d6000fd5b5050606b80546001600160a01b0319166001600160a01b03851617905550506040517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219062001acf9083906200228d565b60405180910390a150565b62001ae462000a72565b62001b035760405162461bcd60e51b81526004016200068e9062002448565b6001600160a01b03811662001b4b5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b60448201526064016200068e565b620015c6815b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8360665462001bb3919062002495565b606681905560408051918252602082018690526001600160a01b03858116838301526060830185905283166080830152517f3b50eb9d9b4a8db204f2928c9e572c2865b0d02803493ccb6aa256848323ebb79181900360a00190a150505050565b600060405162001c249062001da0565b604051809103906000f08015801562001c41573d6000803e3d6000fd5b50607280546001600160a01b03929092166001600160a01b03199283168117909155607180549092168117909155919050565b60405163aae4b8f760e01b815260009083906001600160a01b0382169063aae4b8f79062001ca79086906004016200228d565b60206040518083038186803b15801562001cc057600080fd5b505afa15801562001cd5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001cfb91906200202d565b949350505050565b610f3980620025a083390190565b82805462001d1f906200250f565b90600052602060002090601f01602090048101928262001d43576000855562001d8e565b82601f1062001d5e5782800160ff1982351617855562001d8e565b8280016001018555821562001d8e579182015b8281111562001d8e57823582559160200191906001019062001d71565b5062001d9c92915062001dae565b5090565b6107be80620034d983390190565b5b8082111562001d9c576000815560010162001daf565b600082601f83011262001dd757600080fd5b81356001600160401b038082111562001df45762001df462002562565b604051601f8301601f19908116603f0116810190828211818310171562001e1f5762001e1f62002562565b8160405283815286602085880101111562001e3957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008083601f84011262001e6c57600080fd5b5081356001600160401b0381111562001e8457600080fd5b602083019150836020828501011115620005bb57600080fd5b60006020828403121562001eb057600080fd5b81356200071a8162002578565b60006020828403121562001ed057600080fd5b81516200071a8162002578565b6000806040838503121562001ef157600080fd5b823562001efe8162002578565b9150602083013562001f10816200258e565b809150509250929050565b6000806040838503121562001f2f57600080fd5b823562001f3c8162002578565b9150602083013562001f108162002578565b60008060008060008060008060c0898b03121562001f6b57600080fd5b883562001f788162002578565b9750602089013562001f8a8162002578565b96506040890135955060608901356001600160401b038082111562001fae57600080fd5b62001fbc8c838d0162001e59565b909750955060808b013591508082111562001fd657600080fd5b5062001fe58b828c0162001e59565b999c989b50969995989497949560a00135949350505050565b600080604083850312156200201257600080fd5b82356200201f8162002578565b946020939093013593505050565b6000602082840312156200204057600080fd5b815180151581146200071a57600080fd5b6000602082840312156200206457600080fd5b81356001600160401b038111156200207b57600080fd5b62001cfb8482850162001dc5565b600080604083850312156200209d57600080fd5b82356001600160401b03811115620020b457600080fd5b620020c28582860162001dc5565b925050602083013562001f10816200258e565b600060208284031215620020e857600080fd5b81356200071a816200258e565b6000602082840312156200210857600080fd5b81516200071a816200258e565b6000602082840312156200212857600080fd5b5051919050565b600080604083850312156200214357600080fd5b82359150602083013562001f108162002578565b600080600080600080600060c0888a0312156200217357600080fd5b873596506020880135620021878162002578565b9550604088013594506060880135935060808801356001600160401b03811115620021b157600080fd5b620021bf8a828b0162001e59565b90945092505060a08801356001600160a01b031981168114620021e157600080fd5b8091505092959891949750929550565b600080604083850312156200220557600080fd5b50508035926020909101359150565b6000815180845260005b818110156200223c576020818501810151868301820152016200221e565b818111156200224f576000602083870101525b50601f01601f19169290920160200192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0391909116815260200190565b6001600160a01b03848116825283166020820152606060408201819052600090620022cf9083018462002214565b95945050505050565b6001600160a01b038981168252881660208201526040810187905260c0606082018190526000906200230e908301878962002264565b82810360808401526200232381868862002264565b9150508260a08301529998505050505050505050565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b03929092168252602082015260400190565b600060018060a01b03808a16835288602084015280881660408401525085606083015284608083015260c060a0830152620006f460c08301848662002264565b6020815260006200071a602083018462002214565b6020808252601390820152721053149150511657d253925512505312569151606a1b604082015260600190565b6020808252600a90820152694f4e4c595f4c4f434b5360b01b604082015260600190565b60208082526013908201527226a4a9a9a4a723afa82927ac2cafa0a226a4a760691b604082015260600190565b6020808252600a908201526927a7262cafa7aba722a960b11b604082015260600190565b600061ffff8083168185168083038211156200248c576200248c6200254c565b01949350505050565b60008219821115620024ab57620024ab6200254c565b500190565b600082620024ce57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615620024f057620024f06200254c565b500290565b6000828210156200250a576200250a6200254c565b500390565b600181811c908216806200252457607f821691505b602082108114156200254657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114620015c657600080fd5b61ffff81168114620015c657600080fdfe608060405260405162000f3938038062000f398339810160408190526200002691620004c2565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f5565b60008051602062000ef2833981519152146200007557620000756200064a565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f5565b60008051602062000ed283398151915214620000d357620000d36200064a565b620000de8262000124565b50505062000676565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002601760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e9838360405180606001604052806027815260200162000f126027913962000381565b9392505050565b60006200021a60008051602062000ed283398151915260001b6200045e60201b620002081760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd60008051602062000ed283398151915260001b6200045e60201b620002081760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046160201b6200028c1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd60008051602062000ef283398151915260001b6200045e60201b620002081760201c565b6060833b620003e25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b031685604051620003ff9190620005a2565b600060405180830381855af49150503d80600081146200043c576040519150601f19603f3d011682016040523d82523d6000602084013e62000441565b606091505b5090925090506200045482828662000467565b9695505050505050565b90565b3b151590565b6060831562000478575081620001e9565b825115620004895782518084602001fd5b8160405162461bcd60e51b81526004016200028b9190620005c0565b80516001600160a01b0381168114620004bd57600080fd5b919050565b600080600060608486031215620004d857600080fd5b620004e384620004a5565b9250620004f360208501620004a5565b60408501519092506001600160401b03808211156200051157600080fd5b818601915086601f8301126200052657600080fd5b8151818111156200053b576200053b62000660565b604051601f8201601f19908116603f0116810190838211818310171562000566576200056662000660565b816040528281528960208487010111156200058057600080fd5b620005938360208301602088016200061b565b80955050505050509250925092565b60008251620005b68184602087016200061b565b9190910192915050565b6020815260008251806020840152620005e18160408501602087016200061b565b601f01601f19169190910160400192915050565b6000828210156200061657634e487b7160e01b600052601160045260246000fd5b500390565b60005b83811015620006385781810151838201526020016200061e565b838111156200011d5750506000910152565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61084c80620006866000396000f3fe60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106d6565b610118565b61005b6100933660046106f1565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106d6565b61020b565b3480156100f557600080fd5b506100ad610235565b610106610292565b610116610111610331565b61033b565b565b61012061035f565b6001600160a01b0316336001600160a01b031614156101575761015481604051806020016040528060008152506000610392565b50565b6101546100fe565b61016761035f565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610392915050565b505050565b6101c36100fe565b60006101da61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb610331565b905090565b6102086100fe565b90565b61021361035f565b6001600160a01b0316336001600160a01b0316141561015757610154816103bd565b600061023f61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb61035f565b606061028583836040518060600160405280602781526020016107f060279139610411565b9392505050565b3b151590565b61029a61035f565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104e5565b3660008037600080366000845af43d6000803e80801561035a573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61039b8361050d565b6000825111806103a85750805b156101c3576103b78383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e661035f565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161054d565b6060833b6104705760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610328565b600080856001600160a01b03168560405161048b9190610774565b600060405180830381855af49150503d80600081146104c6576040519150601f19603f3d011682016040523d82523d6000602084013e6104cb565b606091505b50915091506104db8282866105f6565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610383565b6105168161062f565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105b25760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610328565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610605575081610285565b8251156106155782518084602001fd5b8160405162461bcd60e51b81526004016103289190610790565b803b6106935760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610328565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105d5565b80356001600160a01b03811681146106d157600080fd5b919050565b6000602082840312156106e857600080fd5b610285826106ba565b60008060006040848603121561070657600080fd5b61070f846106ba565b9250602084013567ffffffffffffffff8082111561072c57600080fd5b818601915086601f83011261074057600080fd5b81358181111561074f57600080fd5b87602082850101111561076157600080fd5b6020830194508093505050509250925092565b600082516107868184602087016107c3565b9190910192915050565b60208152600082518060208401526107af8160408501602087016107c3565b601f01601f19169190910160400192915050565b60005b838110156107de5781810151838201526020016107c6565b838111156103b7575050600091015256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122069013180797a320073b51923c269b12cc1f6ad3ad59099b708d6ca452b6c416864736f6c63430008070033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6107408061007e6000396000f3fe60806040526004361061006b5760003560e01c8063204e1c7a14610070578063715018a6146100a65780637eff275e146100bd5780638da5cb5b146100dd5780639623609d146100f257806399a88ec414610105578063f2fde38b14610125578063f3b7dead14610145575b600080fd5b34801561007c57600080fd5b5061009061008b3660046104e1565b610165565b60405161009d9190610631565b60405180910390f35b3480156100b257600080fd5b506100bb6101f6565b005b3480156100c957600080fd5b506100bb6100d8366004610522565b61023a565b3480156100e957600080fd5b506100906102cb565b6100bb61010036600461055b565b6102da565b34801561011157600080fd5b506100bb610120366004610522565b610370565b34801561013157600080fd5b506100bb6101403660046104e1565b6103cb565b34801561015157600080fd5b506100906101603660046104e1565b61046b565b6000806000836001600160a01b031660405161018b90635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b5091509150816101da57600080fd5b808060200190518101906101ee9190610505565b949350505050565b336101ff6102cb565b6001600160a01b03161461022e5760405162461bcd60e51b8152600401610225906106aa565b60405180910390fd5b6102386000610491565b565b336102436102cb565b6001600160a01b0316146102695760405162461bcd60e51b8152600401610225906106aa565b6040516308f2839760e41b81526001600160a01b03831690638f28397090610295908490600401610631565b600060405180830381600087803b1580156102af57600080fd5b505af11580156102c3573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031690565b336102e36102cb565b6001600160a01b0316146103095760405162461bcd60e51b8152600401610225906106aa565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906103399086908690600401610645565b6000604051808303818588803b15801561035257600080fd5b505af1158015610366573d6000803e3d6000fd5b5050505050505050565b336103796102cb565b6001600160a01b03161461039f5760405162461bcd60e51b8152600401610225906106aa565b604051631b2ce7f360e11b81526001600160a01b03831690633659cfe690610295908490600401610631565b336103d46102cb565b6001600160a01b0316146103fa5760405162461bcd60e51b8152600401610225906106aa565b6001600160a01b03811661045f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610225565b61046881610491565b50565b6000806000836001600160a01b031660405161018b906303e1469160e61b815260040190565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156104f357600080fd5b81356104fe816106f5565b9392505050565b60006020828403121561051757600080fd5b81516104fe816106f5565b6000806040838503121561053557600080fd5b8235610540816106f5565b91506020830135610550816106f5565b809150509250929050565b60008060006060848603121561057057600080fd5b833561057b816106f5565b9250602084013561058b816106f5565b9150604084013567ffffffffffffffff808211156105a857600080fd5b818601915086601f8301126105bc57600080fd5b8135818111156105ce576105ce6106df565b604051601f8201601f19908116603f011681019083821181831017156105f6576105f66106df565b8160405282815289602084870101111561060f57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6001600160a01b0391909116815260200190565b60018060a01b038316815260006020604081840152835180604085015260005b8181101561068157858101830151858201606001528201610665565b81811115610693576000606083870101525b50601f01601f191692909201606001949350505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461046857600080fdfea2646970667358221220125c3f15bab352eefb1c849f6ce22a786402ca0e764b273ba139e89ca5d91fd764736f6c63430008070033a26469706673582212208276f85b113e4c6bf61a01f1e095ec615afd8bb29e629b7aac28d14a42b0636b64736f6c63430008070033
Deployed Bytecode
0x60806040523480156200001157600080fd5b50600436106200021d5760003560e01c80638da5cb5b1162000127578063c4d66de811620000b6578063c4d66de81462000503578063c7d7d0c9146200051a578063caeee3a31462000524578063ccf54648146200053b578063cd93b5321462000552578063cec410521462000561578063d6e9e803146200056b578063ef67fde61462000575578063f2fde38b146200058c578063f832899114620005a357600080fd5b80638da5cb5b146200046c5780638f32d59b146200047e578063939d9f1f1462000499578063963a947814620004b05780639a8a059214620004c7578063a082eb0e14620004d1578063a998e9fb14620004db578063b0ca0c8314620004e5578063ba5ea0d514620004fc57600080fd5b8063487a8a7611620001b0578063487a8a7614620003365780635979e755146200034d5780635c38eb3a14620003615780635de9a1371462000378578063666018a514620003cc5780636bced5a214620003fc578063715018a61462000428578063743bbc2f14620004325780637d8fb641146200044b5780637ff94bb2146200046257600080fd5b80630cb175e3146200022257806325772ad91462000253578063262d0a85146200029757806335a750de14620002ba5780633652466314620002d35780633fc8cef314620002ec5780634220bd46146200030057806342d9210614620003085780634452c2b2146200031f575b600080fd5b620002396200023336600462001ffe565b620005b7565b604080519283526020830191909152015b60405180910390f35b620002836200026436600462001e9d565b6001600160a01b031660009081526073602052604090205461ffff1690565b60405161ffff90911681526020016200024a565b606e54620002ab906001600160a01b031681565b6040516200024a91906200228d565b620002c4620005c2565b6040516200024a9190620023b5565b620002ea620002e4366004620021f1565b6200065c565b005b606d54620002ab906001600160a01b031681565b600b62000283565b620002ab6200031936600462002157565b6200069b565b620002ab6200033036600462002051565b62000701565b620002ab6200034736600462002089565b62000721565b607154620002ab906001600160a01b031681565b620002ea6200037236600462001f1b565b6200088e565b620003ae6200038936600462001e9d565b60686020526000908152604090208054600182015460029092015460ff909116919083565b6040805193151584526020840192909252908201526060016200024a565b620002ab620003dd366004620020d5565b61ffff166000908152607460205260409020546001600160a01b031690565b620002ab6200040d36600462001e9d565b606c602052600090815260409020546001600160a01b031681565b620002ea62000957565b6200043c606f5481565b6040519081526020016200024a565b620002ea6200045c36600462001f4e565b6200098e565b620002c462000a61565b6033546001600160a01b0316620002ab565b6200048862000a72565b60405190151581526020016200024a565b620002ea620004aa3660046200212f565b62000a83565b620002ea620004c1366004620021f1565b620012ee565b6200043c60705481565b6200043c60675481565b620002c46200135e565b620002ea620004f636600462001e9d565b620013f4565b486200043c565b620002ea6200051436600462001e9d565b620014b6565b620002ea62001545565b620002ea6200053536600462001edd565b620015c9565b620002ab6200054c36600462001edd565b62001697565b607554620002839061ffff1681565b620002c462001970565b6200043c60665481565b620002ea6200058636600462001e9d565b6200197f565b620002ea6200059d36600462001e9d565b62001ada565b606b54620002ab906001600160a01b031681565b6000805b9250929050565b6060606a8054620005d3906200250f565b80601f016020809104026020016040519081016040528092919081815260200182805462000601906200250f565b8015620006525780601f10620006265761010080835404028352916020019162000652565b820191906000526020600020905b8154815290600101906020018083116200063457829003601f168201915b5050505050905090565b3360009081526068602052604090205460ff16620006975760405162461bcd60e51b81526004016200068e90620023f7565b60405180910390fd5b5050565b60008033898989898989604051602401620006bd979695949392919062002375565b60408051601f198184030181529190526020810180516001600160e01b0316636eadde4360e01b1790529050620006f48162000701565b9998505050505050505050565b60755460009081906200071a90849061ffff1662000721565b9392505050565b6071546000906001600160a01b03166200074f5760405162461bcd60e51b81526004016200068e906200241b565b61ffff82166000908152607460205260409020546001600160a01b031680620007b35760405162461bcd60e51b81526020600482015260156024820152744d495353494e475f4c4f434b5f54454d504c41544560581b60448201526064016200068e565b60715460405160009183916001600160a01b03909116908790620007d79062001d03565b620007e593929190620022a1565b604051809103906000f08015801562000802573d6000803e3d6000fd5b50604080516060810182526001808252600060208084018281528486018381526001600160a01b03881680855260689093528684209551865460ff191690151517865590519385019390935591516002909301929092559151929350839233917f01017ed19df0c7f8acc436147b234b09664a9fb4797b4fa3fb9e599c2eb67be791a395945050505050565b6200089862000a72565b620008b75760405162461bcd60e51b81526004016200068e9062002448565b6001600160a01b038281166000908152606c6020526040902080546001600160a01b0319169183169182179055156200069757606d5460405163c640752d60e01b81526001600160a01b03848116600483015291821660248201529082169063c640752d90604401600060405180830381600087803b1580156200093a57600080fd5b505af11580156200094f573d6000803e3d6000fd5b505050505050565b6200096162000a72565b620009805760405162461bcd60e51b81526004016200068e9062002448565b6200098c600062001b51565b565b6200099862000a72565b620009b75760405162461bcd60e51b81526004016200068e9062002448565b606e80546001600160a01b03808b166001600160a01b031992831617909255606d8054928a1692909116919091179055606f869055620009fa606a868662001d11565b5062000a096069848462001d11565b5060708190556040517fa14230a1687e9bb8cdc0f3931d27c3a806e88c1c2235ba7756d6911feb35be679062000a4f908a908a908a908a908a908a908a908a90620022d8565b60405180910390a15050505050505050565b606060698054620005d3906200250f565b6033546001600160a01b0316331490565b3360009081526068602052604090205460ff1662000ab55760405162461bcd60e51b81526004016200068e90620023f7565b81156200069757600080336001600160a01b0316639d76ea586040518163ffffffff1660e01b815260040160206040518083038186803b15801562000af957600080fd5b505afa15801562000b0e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000b34919062001ebd565b90506001600160a01b0381161580159062000b5d5750606d546001600160a01b03828116911614155b1562000c1c576001600160a01b038082166000908152606c602052604090205416801562000c1557606d5460405163c1e553e760e01b81526001600160a01b038084169263c1e553e79262000bbc9287928b9291169060040162002339565b602060405180830381600087803b15801562000bd757600080fd5b505af115801562000bec573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000c12919062002115565b92505b5062000c20565b8391505b62000c2e8282863362001ba3565b336000908152606860205260408120600101805484929062000c5290849062002495565b90915550506001600160a01b03831615620012e857606e546001600160a01b039081166000908152606c6020526040902054168015620012e657606e54606d5460405163c1e553e760e01b81526000926001600160a01b038086169363c1e553e79362000cd193831692670de0b6b3a764000092169060040162002339565b602060405180830381600087803b15801562000cec57600080fd5b505af115801562000d01573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d27919062002115565b90506000306001600160a01b031663ba5ea0d56040518163ffffffff1660e01b815260040160206040518083038186803b15801562000d6557600080fd5b505afa92505050801562000d98575060408051601f3d908101601f1916820190925262000d959181019062002115565b60015b62000da65750606462000dbc565b8062000db6576064915062000dba565b8091505b505b600082606483606f5462000dd19190620024d3565b62000de6906806c6b935b8bbd40000620024d3565b62000df29190620024b0565b62000dfe9190620024b0565b905060006001607054111562000eec576066548062000e1f896002620024d3565b62000e2b9190620024b0565b62000e3890600262002495565b606e546040516370a0823160e01b81528a916001600160a01b0316906370a082319062000e6a9030906004016200228d565b602060405180830381600087803b15801562000e8557600080fd5b505af115801562000e9a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ec0919062002115565b62000ecc9190620024d3565b62000ed89190620024b0565b62000ee49190620024b0565b905062000fa5565b606654600288606e60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801562000f4357600080fd5b505af115801562000f58573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f7e919062002115565b62000f8a9190620024d3565b62000f969190620024b0565b62000fa29190620024b0565b90505b8082111562000fb2578091505b8115620012e1576000606462000fca846014620024d3565b62000fd69190620024b0565b905060016070541115620011af57606e546040516370a0823160e01b81526000916001600160a01b0316906370a0823190620010179030906004016200228d565b602060405180830381600087803b1580156200103257600080fd5b505af115801562001047573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200106d919062002115565b905083811115620011a857606e546001600160a01b031663a9059cbb8b620010968588620024f5565b6040518363ffffffff1660e01b8152600401620010b59291906200235c565b602060405180830381600087803b158015620010d057600080fd5b505af1158015620010e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200110b91906200202d565b50606e546001600160a01b031663a9059cbb620011306033546001600160a01b031690565b846040518363ffffffff1660e01b8152600401620011509291906200235c565b602060405180830381600087803b1580156200116b57600080fd5b505af115801562001180573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011a691906200202d565b505b50620012df565b606e546001600160a01b03166340c10f198a620011cd8487620024f5565b6040518363ffffffff1660e01b8152600401620011ec9291906200235c565b602060405180830381600087803b1580156200120757600080fd5b505af11580156200121c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200124291906200202d565b50606e546001600160a01b03166340c10f19620012676033546001600160a01b031690565b836040518363ffffffff1660e01b8152600401620012879291906200235c565b602060405180830381600087803b158015620012a257600080fd5b505af1158015620012b7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620012dd91906200202d565b505b505b505050505b505b50505050565b620012f862000a72565b620013175760405162461bcd60e51b81526004016200068e9062002448565b6066829055606781905560408051838152602081018390527f7b2ce3c83b45f79993ff2cbf5651caff2dfe04010b4846e03066b84e3e4059bb910160405180910390a15050565b606980546200136d906200250f565b80601f01602080910402602001604051908101604052809291908181526020018280546200139b906200250f565b8015620013ec5780601f10620013c057610100808354040283529160200191620013ec565b820191906000526020600020905b815481529060010190602001808311620013ce57829003601f168201915b505050505081565b600054610100900460ff16620014115760005460ff161562001415565b303b155b620014345760405162461bcd60e51b81526004016200068e90620023ca565b600054610100900460ff1615801562001457576000805461ffff19166101011790555b603380546001600160a01b0319166001600160a01b0384169081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3801562000697576000805461ff00191690555050565b600054610100900460ff16620014d35760005460ff1615620014d7565b303b155b620014f65760405162461bcd60e51b81526004016200068e90620023ca565b600054610100900460ff1615801562001519576000805461ffff19166101011790555b6200152482620013f4565b6200152e62001c14565b50801562000697576000805461ff00191690555050565b6200154f62000a72565b6200156e5760405162461bcd60e51b81526004016200068e9062002448565b6071546001600160a01b031615620015bc5760405162461bcd60e51b815260206004820152601060248201526f1053149150511657d111541313d6515160821b60448201526064016200068e565b620015c662001c14565b50565b620015d362000a72565b620015f25760405162461bcd60e51b81526004016200068e9062002448565b6001600160a01b0382166000818152607360209081526040808320805461ffff191661ffff8781169182179092558085526074909352922080546001600160a01b03191690931790925560755416101562001659576075805461ffff191661ffff83161790555b60405161ffff8216906001600160a01b038416907fd36d021c4aa145e30eadc73e34284101030d688b9eb9413a4dc3af40ab1d474890600090a35050565b6071546000906001600160a01b0316620016c55760405162461bcd60e51b81526004016200068e906200241b565b620016d1833362001c74565b1515600114620017135760405162461bcd60e51b815260206004820152600c60248201526b4d414e414745525f4f4e4c5960a01b60448201526064016200068e565b60008390506000816001600160a01b031663d1bbd49c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200175457600080fd5b505afa15801562001769573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200178f9190620020f5565b90506200179e8160016200246c565b61ffff168461ffff1614620017e95760405162461bcd60e51b815260206004820152601060248201526f0ac8aa4a6929e9cbea89e9ebe90928e960831b60448201526064016200068e565b61ffff84166000908152607460205260409020546001600160a01b031680620018485760405162461bcd60e51b815260206004820152601060248201526f4d495353494e475f54454d504c41544560801b60448201526064016200068e565b60725460405163266a23b160e21b81526001600160a01b0380891660048301528381166024830152889216906399a88ec490604401600060405180830381600087803b1580156200189857600080fd5b505af1158015620018ad573d6000803e3d6000fd5b5050604051638932a90d60e01b8152602060048201526002602482015261060f60f31b60448201526001600160a01b0387169250638932a90d9150606401600060405180830381600087803b1580156200190657600080fd5b505af11580156200191b573d6000803e3d6000fd5b5050604080516001600160a01b038b16815261ffff8a1660208201527f5e7b70a9e6f0b4c7cf2657cf563ce85eed3aebb7731396118d01a195d218fd5e935001905060405180910390a1509495945050505050565b606a80546200136d906200250f565b6200198962000a72565b620019a85760405162461bcd60e51b81526004016200068e9062002448565b604051636eadde4360e01b815230600482015260006024820181905260448201819052606482018190526084820181905260c060a483015260c48201526001600160a01b03821690636eadde439060e401600060405180830381600087803b15801562001a1457600080fd5b505af115801562001a29573d6000803e3d6000fd5b50505050806001600160a01b031663f0ba60406040518163ffffffff1660e01b8152600401600060405180830381600087803b15801562001a6957600080fd5b505af115801562001a7e573d6000803e3d6000fd5b5050606b80546001600160a01b0319166001600160a01b03851617905550506040517f4fa58418e580e78539e8d3d8d17d94dbaca0927533953c8248f313e6f8927c219062001acf9083906200228d565b60405180910390a150565b62001ae462000a72565b62001b035760405162461bcd60e51b81526004016200068e9062002448565b6001600160a01b03811662001b4b5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa7aba722a960991b60448201526064016200068e565b620015c6815b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8360665462001bb3919062002495565b606681905560408051918252602082018690526001600160a01b03858116838301526060830185905283166080830152517f3b50eb9d9b4a8db204f2928c9e572c2865b0d02803493ccb6aa256848323ebb79181900360a00190a150505050565b600060405162001c249062001da0565b604051809103906000f08015801562001c41573d6000803e3d6000fd5b50607280546001600160a01b03929092166001600160a01b03199283168117909155607180549092168117909155919050565b60405163aae4b8f760e01b815260009083906001600160a01b0382169063aae4b8f79062001ca79086906004016200228d565b60206040518083038186803b15801562001cc057600080fd5b505afa15801562001cd5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001cfb91906200202d565b949350505050565b610f3980620025a083390190565b82805462001d1f906200250f565b90600052602060002090601f01602090048101928262001d43576000855562001d8e565b82601f1062001d5e5782800160ff1982351617855562001d8e565b8280016001018555821562001d8e579182015b8281111562001d8e57823582559160200191906001019062001d71565b5062001d9c92915062001dae565b5090565b6107be80620034d983390190565b5b8082111562001d9c576000815560010162001daf565b600082601f83011262001dd757600080fd5b81356001600160401b038082111562001df45762001df462002562565b604051601f8301601f19908116603f0116810190828211818310171562001e1f5762001e1f62002562565b8160405283815286602085880101111562001e3957600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008083601f84011262001e6c57600080fd5b5081356001600160401b0381111562001e8457600080fd5b602083019150836020828501011115620005bb57600080fd5b60006020828403121562001eb057600080fd5b81356200071a8162002578565b60006020828403121562001ed057600080fd5b81516200071a8162002578565b6000806040838503121562001ef157600080fd5b823562001efe8162002578565b9150602083013562001f10816200258e565b809150509250929050565b6000806040838503121562001f2f57600080fd5b823562001f3c8162002578565b9150602083013562001f108162002578565b60008060008060008060008060c0898b03121562001f6b57600080fd5b883562001f788162002578565b9750602089013562001f8a8162002578565b96506040890135955060608901356001600160401b038082111562001fae57600080fd5b62001fbc8c838d0162001e59565b909750955060808b013591508082111562001fd657600080fd5b5062001fe58b828c0162001e59565b999c989b50969995989497949560a00135949350505050565b600080604083850312156200201257600080fd5b82356200201f8162002578565b946020939093013593505050565b6000602082840312156200204057600080fd5b815180151581146200071a57600080fd5b6000602082840312156200206457600080fd5b81356001600160401b038111156200207b57600080fd5b62001cfb8482850162001dc5565b600080604083850312156200209d57600080fd5b82356001600160401b03811115620020b457600080fd5b620020c28582860162001dc5565b925050602083013562001f10816200258e565b600060208284031215620020e857600080fd5b81356200071a816200258e565b6000602082840312156200210857600080fd5b81516200071a816200258e565b6000602082840312156200212857600080fd5b5051919050565b600080604083850312156200214357600080fd5b82359150602083013562001f108162002578565b600080600080600080600060c0888a0312156200217357600080fd5b873596506020880135620021878162002578565b9550604088013594506060880135935060808801356001600160401b03811115620021b157600080fd5b620021bf8a828b0162001e59565b90945092505060a08801356001600160a01b031981168114620021e157600080fd5b8091505092959891949750929550565b600080604083850312156200220557600080fd5b50508035926020909101359150565b6000815180845260005b818110156200223c576020818501810151868301820152016200221e565b818111156200224f576000602083870101525b50601f01601f19169290920160200192915050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0391909116815260200190565b6001600160a01b03848116825283166020820152606060408201819052600090620022cf9083018462002214565b95945050505050565b6001600160a01b038981168252881660208201526040810187905260c0606082018190526000906200230e908301878962002264565b82810360808401526200232381868862002264565b9150508260a08301529998505050505050505050565b6001600160a01b0393841681526020810192909252909116604082015260600190565b6001600160a01b03929092168252602082015260400190565b600060018060a01b03808a16835288602084015280881660408401525085606083015284608083015260c060a0830152620006f460c08301848662002264565b6020815260006200071a602083018462002214565b6020808252601390820152721053149150511657d253925512505312569151606a1b604082015260600190565b6020808252600a90820152694f4e4c595f4c4f434b5360b01b604082015260600190565b60208082526013908201527226a4a9a9a4a723afa82927ac2cafa0a226a4a760691b604082015260600190565b6020808252600a908201526927a7262cafa7aba722a960b11b604082015260600190565b600061ffff8083168185168083038211156200248c576200248c6200254c565b01949350505050565b60008219821115620024ab57620024ab6200254c565b500190565b600082620024ce57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615620024f057620024f06200254c565b500290565b6000828210156200250a576200250a6200254c565b500390565b600181811c908216806200252457607f821691505b602082108114156200254657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114620015c657600080fd5b61ffff81168114620015c657600080fdfe608060405260405162000f3938038062000f398339810160408190526200002691620004c2565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f5565b60008051602062000ef2833981519152146200007557620000756200064a565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f5565b60008051602062000ed283398151915214620000d357620000d36200064a565b620000de8262000124565b50505062000676565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002601760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e9838360405180606001604052806027815260200162000f126027913962000381565b9392505050565b60006200021a60008051602062000ed283398151915260001b6200045e60201b620002081760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd60008051602062000ed283398151915260001b6200045e60201b620002081760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046160201b6200028c1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd60008051602062000ef283398151915260001b6200045e60201b620002081760201c565b6060833b620003e25760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b031685604051620003ff9190620005a2565b600060405180830381855af49150503d80600081146200043c576040519150601f19603f3d011682016040523d82523d6000602084013e62000441565b606091505b5090925090506200045482828662000467565b9695505050505050565b90565b3b151590565b6060831562000478575081620001e9565b825115620004895782518084602001fd5b8160405162461bcd60e51b81526004016200028b9190620005c0565b80516001600160a01b0381168114620004bd57600080fd5b919050565b600080600060608486031215620004d857600080fd5b620004e384620004a5565b9250620004f360208501620004a5565b60408501519092506001600160401b03808211156200051157600080fd5b818601915086601f8301126200052657600080fd5b8151818111156200053b576200053b62000660565b604051601f8201601f19908116603f0116810190838211818310171562000566576200056662000660565b816040528281528960208487010111156200058057600080fd5b620005938360208301602088016200061b565b80955050505050509250925092565b60008251620005b68184602087016200061b565b9190910192915050565b6020815260008251806020840152620005e18160408501602087016200061b565b601f01601f19169190910160400192915050565b6000828210156200061657634e487b7160e01b600052601160045260246000fd5b500390565b60005b83811015620006385781810151838201526020016200061e565b838111156200011d5750506000910152565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b61084c80620006866000396000f3fe60806040526004361061004e5760003560e01c80633659cfe6146100655780634f1ef286146100855780635c60da1b146100985780638f283970146100c9578063f851a440146100e95761005d565b3661005d5761005b6100fe565b005b61005b6100fe565b34801561007157600080fd5b5061005b6100803660046106d6565b610118565b61005b6100933660046106f1565b61015f565b3480156100a457600080fd5b506100ad6101d0565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d557600080fd5b5061005b6100e43660046106d6565b61020b565b3480156100f557600080fd5b506100ad610235565b610106610292565b610116610111610331565b61033b565b565b61012061035f565b6001600160a01b0316336001600160a01b031614156101575761015481604051806020016040528060008152506000610392565b50565b6101546100fe565b61016761035f565b6001600160a01b0316336001600160a01b031614156101c8576101c38383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525060019250610392915050565b505050565b6101c36100fe565b60006101da61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb610331565b905090565b6102086100fe565b90565b61021361035f565b6001600160a01b0316336001600160a01b0316141561015757610154816103bd565b600061023f61035f565b6001600160a01b0316336001600160a01b03161415610200576101fb61035f565b606061028583836040518060600160405280602781526020016107f060279139610411565b9392505050565b3b151590565b61029a61035f565b6001600160a01b0316336001600160a01b031614156101165760405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b60006101fb6104e5565b3660008037600080366000845af43d6000803e80801561035a573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b61039b8361050d565b6000825111806103a85750805b156101c3576103b78383610260565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e661035f565b604080516001600160a01b03928316815291841660208301520160405180910390a16101548161054d565b6060833b6104705760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610328565b600080856001600160a01b03168560405161048b9190610774565b600060405180830381855af49150503d80600081146104c6576040519150601f19603f3d011682016040523d82523d6000602084013e6104cb565b606091505b50915091506104db8282866105f6565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610383565b6105168161062f565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105b25760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610328565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60608315610605575081610285565b8251156106155782518084602001fd5b8160405162461bcd60e51b81526004016103289190610790565b803b6106935760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610328565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105d5565b80356001600160a01b03811681146106d157600080fd5b919050565b6000602082840312156106e857600080fd5b610285826106ba565b60008060006040848603121561070657600080fd5b61070f846106ba565b9250602084013567ffffffffffffffff8082111561072c57600080fd5b818601915086601f83011261074057600080fd5b81358181111561074f57600080fd5b87602082850101111561076157600080fd5b6020830194508093505050509250925092565b600082516107868184602087016107c3565b9190910192915050565b60208152600082518060208401526107af8160408501602087016107c3565b601f01601f19169190910160400192915050565b60005b838110156107de5781810151838201526020016107c6565b838111156103b7575050600091015256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122069013180797a320073b51923c269b12cc1f6ad3ad59099b708d6ca452b6c416864736f6c63430008070033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6107408061007e6000396000f3fe60806040526004361061006b5760003560e01c8063204e1c7a14610070578063715018a6146100a65780637eff275e146100bd5780638da5cb5b146100dd5780639623609d146100f257806399a88ec414610105578063f2fde38b14610125578063f3b7dead14610145575b600080fd5b34801561007c57600080fd5b5061009061008b3660046104e1565b610165565b60405161009d9190610631565b60405180910390f35b3480156100b257600080fd5b506100bb6101f6565b005b3480156100c957600080fd5b506100bb6100d8366004610522565b61023a565b3480156100e957600080fd5b506100906102cb565b6100bb61010036600461055b565b6102da565b34801561011157600080fd5b506100bb610120366004610522565b610370565b34801561013157600080fd5b506100bb6101403660046104e1565b6103cb565b34801561015157600080fd5b506100906101603660046104e1565b61046b565b6000806000836001600160a01b031660405161018b90635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101c6576040519150601f19603f3d011682016040523d82523d6000602084013e6101cb565b606091505b5091509150816101da57600080fd5b808060200190518101906101ee9190610505565b949350505050565b336101ff6102cb565b6001600160a01b03161461022e5760405162461bcd60e51b8152600401610225906106aa565b60405180910390fd5b6102386000610491565b565b336102436102cb565b6001600160a01b0316146102695760405162461bcd60e51b8152600401610225906106aa565b6040516308f2839760e41b81526001600160a01b03831690638f28397090610295908490600401610631565b600060405180830381600087803b1580156102af57600080fd5b505af11580156102c3573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031690565b336102e36102cb565b6001600160a01b0316146103095760405162461bcd60e51b8152600401610225906106aa565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906103399086908690600401610645565b6000604051808303818588803b15801561035257600080fd5b505af1158015610366573d6000803e3d6000fd5b5050505050505050565b336103796102cb565b6001600160a01b03161461039f5760405162461bcd60e51b8152600401610225906106aa565b604051631b2ce7f360e11b81526001600160a01b03831690633659cfe690610295908490600401610631565b336103d46102cb565b6001600160a01b0316146103fa5760405162461bcd60e51b8152600401610225906106aa565b6001600160a01b03811661045f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610225565b61046881610491565b50565b6000806000836001600160a01b031660405161018b906303e1469160e61b815260040190565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156104f357600080fd5b81356104fe816106f5565b9392505050565b60006020828403121561051757600080fd5b81516104fe816106f5565b6000806040838503121561053557600080fd5b8235610540816106f5565b91506020830135610550816106f5565b809150509250929050565b60008060006060848603121561057057600080fd5b833561057b816106f5565b9250602084013561058b816106f5565b9150604084013567ffffffffffffffff808211156105a857600080fd5b818601915086601f8301126105bc57600080fd5b8135818111156105ce576105ce6106df565b604051601f8201601f19908116603f011681019083821181831017156105f6576105f66106df565b8160405282815289602084870101111561060f57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6001600160a01b0391909116815260200190565b60018060a01b038316815260006020604081840152835180604085015260005b8181101561068157858101830151858201606001528201610665565b81811115610693576000606083870101525b50601f01601f191692909201606001949350505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461046857600080fdfea2646970667358221220125c3f15bab352eefb1c849f6ce22a786402ca0e764b273ba139e89ca5d91fd764736f6c63430008070033a26469706673582212208276f85b113e4c6bf61a01f1e095ec615afd8bb29e629b7aac28d14a42b0636b64736f6c63430008070033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.