Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Buy And Claim Va... | 19439493 | 284 days ago | IN | 0 ETH | 0.00516811 |
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:
FlooringPeriphery
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 800 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import {UUPSUpgradeable} from "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol"; import "@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol"; import {IFlooring} from "./interface/IFlooring.sol"; import {OwnedUpgradeable} from "./library/OwnedUpgradeable.sol"; import {CurrencyTransfer} from "./library/CurrencyTransfer.sol"; import {ERC721Transfer} from "./library/ERC721Transfer.sol"; import {TicketRecord, SafeBoxKey, SafeBox} from "./logic/Structs.sol"; import "./logic/SafeBox.sol"; import "./Errors.sol"; import "./Constants.sol"; import {FlooringGetter} from "./FlooringGetter.sol"; import "./interface/IWETH9.sol"; import "./Multicall.sol"; contract FlooringPeriphery is FlooringGetter, OwnedUpgradeable, UUPSUpgradeable, IERC721Receiver, Multicall { error NotRouterOrWETH9(); error InsufficientWETH9(); address public immutable uniswapRouter; address public immutable WETH9; constructor(address flooring, address uniswapV3Router, address _WETH9) payable FlooringGetter(flooring) { uniswapRouter = uniswapV3Router; WETH9 = _WETH9; } // required by the OZ UUPS module function _authorizeUpgrade(address) internal override onlyOwner {} function initialize() public initializer { __Owned_init(); __UUPSUpgradeable_init(); } function fragmentAndSell( address collection, uint256[] calldata tokenIds, bool unwrapWETH, ISwapRouter.ExactInputParams memory swapParam ) external payable returns (uint256 swapOut) { uint256 fragmentTokenAmount = tokenIds.length * Constants.FLOOR_TOKEN_AMOUNT; address floorToken = fragmentTokenOf(collection); /// approve all approveAllERC721(collection, address(_flooring)); approveAllERC20(floorToken, uniswapRouter, fragmentTokenAmount); /// transfer tokens into this ERC721Transfer.safeBatchTransferFrom(collection, msg.sender, address(this), tokenIds); /// fragment _flooring.fragmentNFTs(collection, tokenIds, msg.sender); IERC20(floorToken).transferFrom(msg.sender, address(this), fragmentTokenAmount); swapOut = ISwapRouter(uniswapRouter).exactInput(swapParam); if (unwrapWETH) { unwrapWETH9(swapOut, msg.sender); } } function buyAndClaimExpired( address collection, uint256[] calldata tokenIds, uint256 claimCnt, uint256 maxCostToClaim, address swapTokenIn, ISwapRouter.ExactOutputParams memory swapParam ) external payable returns (uint256 tokenCost, uint256 claimCost) { _flooring.tidyExpiredNFTs(collection, tokenIds); return buyAndClaimVault(collection, claimCnt, maxCostToClaim, swapTokenIn, swapParam); } function buyAndClaimVault( address collection, uint256 claimCnt, uint256 maxCostToClaim, address swapTokenIn, ISwapRouter.ExactOutputParams memory swapParam ) public payable returns (uint256 tokenCost, uint256 claimCost) { uint256 fragmentTokenAmount = claimCnt * Constants.FLOOR_TOKEN_AMOUNT; address floorToken = fragmentTokenOf(collection); approveAllERC20(floorToken, address(_flooring), fragmentTokenAmount); tokenCost = swapExactOutput(msg.sender, swapTokenIn, swapParam); uint256 feeCost = swapParam.amountOut > fragmentTokenAmount ? swapParam.amountOut - fragmentTokenAmount : 0; if (feeCost > 0) { _flooring.addTokens(address(this), floorToken, feeCost); } claimCost = _flooring.claimRandomNFT(collection, claimCnt, maxCostToClaim, msg.sender); /// no extra fee or fee matching require(feeCost == 0 || claimCost == feeCost); } function unwrapWETH9(uint256 amountMinimum, address recipient) public payable { uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this)); if (balanceWETH9 < amountMinimum) { revert InsufficientWETH9(); } if (balanceWETH9 > 0) { IWETH9(WETH9).withdraw(balanceWETH9); CurrencyTransfer.safeTransfer(CurrencyTransfer.NATIVE, recipient, balanceWETH9); } } function swapExactOutput(address payer, address tokenIn, ISwapRouter.ExactOutputParams memory param) internal returns (uint256 amountIn) { if (tokenIn == WETH9 && address(this).balance >= param.amountInMaximum) { amountIn = ISwapRouter(uniswapRouter).exactOutput{value: param.amountInMaximum}(param); IPeripheryPayments(uniswapRouter).refundETH(); if (address(this).balance > 0) { CurrencyTransfer.safeTransfer(CurrencyTransfer.NATIVE, payer, address(this).balance); } } else { approveAllERC20(tokenIn, uniswapRouter, param.amountInMaximum); CurrencyTransfer.safeTransferFrom(tokenIn, payer, address(this), param.amountInMaximum); amountIn = ISwapRouter(uniswapRouter).exactOutput(param); if (param.amountInMaximum > amountIn) { CurrencyTransfer.safeTransfer(tokenIn, payer, param.amountInMaximum - amountIn); } } } function approveAllERC20(address token, address spender, uint256 desireAmount) private { if (desireAmount == 0) { return; } uint256 allowance = IERC20(token).allowance(address(this), spender); if (allowance < desireAmount) { IERC20(token).approve(spender, type(uint256).max); } } function approveAllERC721(address collection, address spender) private { bool approved = IERC721(collection).isApprovedForAll(address(this), spender); if (!approved) { IERC721(collection).setApprovalForAll(spender, true); } } function onERC721Received(address, /*operator*/ address, /*from*/ uint256, /*tokenId*/ bytes calldata /*data*/ ) external pure override returns (bytes4) { return this.onERC721Received.selector; } receive() external payable { if (msg.sender != uniswapRouter && msg.sender != WETH9) revert NotRouterOrWETH9(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC1967-compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @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. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.20; import {IBeacon} from "../beacon/IBeacon.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @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 { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * 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 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 { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-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 the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or * {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be * reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.5.0; /// @title Immutable state /// @notice Functions that return immutable state of the router interface IPeripheryImmutableState { /// @return Returns the address of the Uniswap V3 factory function factory() external view returns (address); /// @return Returns the address of WETH9 function WETH9() external view returns (address); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; /// @title Periphery Payments /// @notice Functions to ease deposits and withdrawals of ETH interface IPeripheryPayments { /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH. /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users. /// @param amountMinimum The minimum amount of WETH9 to unwrap /// @param recipient The address receiving ETH function unwrapWETH9(uint256 amountMinimum, address recipient) external payable; /// @notice Refunds any ETH balance held by this contract to the `msg.sender` /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps /// that use ether for the input amount function refundETH() external payable; /// @notice Transfers the full amount of a token held by this contract to recipient /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users /// @param token The contract address of the token which will be transferred to `recipient` /// @param amountMinimum The minimum amount of token required for a transfer /// @param recipient The destination address of the token function sweepToken( address token, uint256 amountMinimum, address recipient ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; pragma abicoder v2; import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface ISwapRouter is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; library Constants { /// @notice Flooring protocol /// @dev floor token amount of 1 NFT (with 18 decimals) uint256 public constant FLOOR_TOKEN_AMOUNT = 1_000_000 ether; /// @dev The minimum vip level required to use `proxy collection` uint8 public constant PROXY_COLLECTION_VIP_THRESHOLD = 3; /// @notice Rolling Bucket Constant Conf uint256 public constant BUCKET_SPAN_1 = 259199 seconds; // BUCKET_SPAN minus 1, used for rounding up uint256 public constant BUCKET_SPAN = 3 days; uint256 public constant MAX_LOCKING_BUCKET = 240; uint256 public constant MAX_LOCKING_PERIOD = 720 days; // MAX LOCKING BUCKET * BUCKET_SPAN /// @notice Auction Config uint256 public constant FREE_AUCTION_PERIOD = 24 hours; uint256 public constant AUCTION_INITIAL_PERIODS = 24 hours; uint256 public constant AUCTION_COMPLETE_GRACE_PERIODS = 2 days; /// @dev admin fee charged per NFT when someone starts aution on expired safebox uint256 public constant AUCTION_ON_EXPIRED_SAFEBOX_COST = 0; /// @dev admin fee charged per NFT when owner starts aution on himself safebox uint256 public constant AUCTION_COST = 100 ether; /// @notice Raffle Config uint256 public constant RAFFLE_COST = 500 ether; uint256 public constant RAFFLE_COMPLETE_GRACE_PERIODS = 2 days; /// @notice Private offer Config uint256 public constant PRIVATE_OFFER_DURATION = 24 hours; uint256 public constant PRIVATE_OFFER_COMPLETE_GRACE_DURATION = 2 days; uint256 public constant PRIVATE_OFFER_COST = 0; uint256 public constant ADD_FREE_NFT_REWARD = 0; /// @notice Lock/Unlock config uint256 public constant USER_SAFEBOX_QUOTA_REFRESH_DURATION = 1 days; uint256 public constant USER_REDEMPTION_WAIVER_REFRESH_DURATION = 1 days; /// @notice The max percentage of the collection that one user can lock uint256 public constant USER_COLLECTION_LOCKED_BOUND_PCT = 50; /// @notice The max locking ratio of the collection that the NFTs in the vault can be redeemed uint256 public constant VAULT_REDEMPTION_MAX_LOKING_RATIO = 80; uint256 public constant VAULT_QUOTA_RESET_PERIOD = 5 days; /// @notice Activities Fee Rate /// @notice Fee rate used to distribute funds that collected from Auctions on expired safeboxes. /// these auction would be settled using credit token uint256 public constant FREE_AUCTION_FEE_RATE_BIPS = 2000; // 20% uint256 public constant VIP_LEVEL_COUNT = 8; struct AuctionBidOption { uint256 extendDurationSecs; uint256 minimumRaisePct; uint256 vipLevel; } function getVipLockingBuckets(uint256 vipLevel) internal pure returns (uint256 buckets) { require(vipLevel < VIP_LEVEL_COUNT); assembly { switch vipLevel case 1 { buckets := 1 } case 2 { buckets := 5 } case 3 { buckets := 20 } case 4 { buckets := 60 } case 5 { buckets := 120 } case 6 { buckets := 180 } case 7 { buckets := MAX_LOCKING_BUCKET } } } function getVipLevel(uint256 totalCredit) internal pure returns (uint8) { if (totalCredit < 30_000 ether) { return 0; } else if (totalCredit < 100_000 ether) { return 1; } else if (totalCredit < 300_000 ether) { return 2; } else if (totalCredit < 1_000_000 ether) { return 3; } else if (totalCredit < 3_000_000 ether) { return 4; } else if (totalCredit < 10_000_000 ether) { return 5; } else if (totalCredit < 30_000_000 ether) { return 6; } else { return 7; } } function getVipBalanceRequirements(uint256 vipLevel) internal pure returns (uint256 required) { require(vipLevel < VIP_LEVEL_COUNT); assembly { switch vipLevel case 1 { required := 30000 } case 2 { required := 100000 } case 3 { required := 300000 } case 4 { required := 1000000 } case 5 { required := 3000000 } case 6 { required := 10000000 } case 7 { required := 30000000 } } /// credit token should be scaled with 18 decimals(1 ether == 10**18) unchecked { return required * 1 ether; } } function getBidOption(uint256 idx) internal pure returns (AuctionBidOption memory) { require(idx < 4); AuctionBidOption[4] memory bidOptions = [ AuctionBidOption({extendDurationSecs: 5 minutes, minimumRaisePct: 1, vipLevel: 0}), AuctionBidOption({extendDurationSecs: 8 hours, minimumRaisePct: 10, vipLevel: 3}), AuctionBidOption({extendDurationSecs: 16 hours, minimumRaisePct: 20, vipLevel: 5}), AuctionBidOption({extendDurationSecs: 24 hours, minimumRaisePct: 40, vipLevel: 7}) ]; return bidOptions[idx]; } function raffleDurations(uint256 idx) internal pure returns (uint256 vipLevel, uint256 duration) { require(idx < 6); vipLevel = idx; assembly { switch idx case 1 { duration := 1 } case 2 { duration := 2 } case 3 { duration := 3 } case 4 { duration := 5 } case 5 { duration := 7 } } unchecked { duration *= 1 days; } } /// return locking ratio restrictions indicates that the vipLevel can utility infinite lock NFTs at corresponding ratio function getLockingRatioForInfinite(uint8 vipLevel) internal pure returns (uint256 ratio) { assembly { switch vipLevel case 1 { ratio := 0 } case 2 { ratio := 0 } case 3 { ratio := 20 } case 4 { ratio := 30 } case 5 { ratio := 40 } case 6 { ratio := 50 } case 7 { ratio := 80 } } } /// return locking ratio restrictions indicates that the vipLevel can utility safebox to lock NFTs at corresponding ratio function getLockingRatioForSafebox(uint8 vipLevel) internal pure returns (uint256 ratio) { assembly { switch vipLevel case 1 { ratio := 10 } case 2 { ratio := 20 } case 3 { ratio := 30 } case 4 { ratio := 40 } case 5 { ratio := 50 } case 6 { ratio := 60 } case 7 { ratio := 70 } } } function getRequiredStakingWithSelfRatio(uint256 requiredStaking, uint256 selfRatio) internal pure returns (uint256) { if (selfRatio < 10) { return requiredStaking; } return (selfRatio + 1) * requiredStaking / 10; } function getVipRequiredStakingWithDiscount(uint256 requiredStaking, uint8 vipLevel) internal pure returns (uint256) { if (vipLevel < 3) { return requiredStaking; } unchecked { /// the higher vip level, more discount for staking /// discount range: 5% - 25% return requiredStaking * (100 - (vipLevel - 2) * 5) / 100; } } function getRequiredStakingForLockRatio(uint256 locked, uint256 totalManaged) internal pure returns (uint256) { if (totalManaged <= 0) { return 1200 ether; } unchecked { uint256 lockingRatioPct = locked * 100 / totalManaged; if (lockingRatioPct <= 40) { return 1200 ether; } else if (lockingRatioPct < 60) { return 1320 ether + ((lockingRatioPct - 40) >> 1) * 120 ether; } else if (lockingRatioPct < 70) { return 2640 ether + ((lockingRatioPct - 60) >> 1) * 240 ether; } else if (lockingRatioPct < 80) { return 4080 ether + ((lockingRatioPct - 70) >> 1) * 480 ether; } else if (lockingRatioPct < 90) { return 6960 ether + ((lockingRatioPct - 80) >> 1) * 960 ether; } else if (lockingRatioPct < 100) { /// 108000 * 2^x return (108000 ether << ((lockingRatioPct - 90) >> 1)) / 5; } else { return 345600 ether; } } } function getVaultAuctionDurationAtLR(uint256 lockingRatio) internal pure returns (uint256) { if (lockingRatio < 80) return 1 hours; else if (lockingRatio < 85) return 3 hours; else if (lockingRatio < 90) return 6 hours; else if (lockingRatio < 95) return 12 hours; else return 24 hours; } function getSafeboxPeriodQuota(uint8 vipLevel) internal pure returns (uint16 quota) { assembly { switch vipLevel case 0 { quota := 0 } case 1 { quota := 1 } case 2 { quota := 2 } case 3 { quota := 4 } case 4 { quota := 8 } case 5 { quota := 16 } case 6 { quota := 32 } case 7 { quota := 64 } } } function getSafeboxUserQuota(uint8 vipLevel) internal pure returns (uint16 quota) { assembly { switch vipLevel case 0 { quota := 0 } case 1 { quota := 4 } case 2 { quota := 8 } case 3 { quota := 16 } case 4 { quota := 32 } case 5 { quota := 64 } case 6 { quota := 128 } case 7 { quota := 256 } } } function getVaultContQuotaAtLR(uint256 lockingRatio) internal pure returns (uint32 contQuota) { if (lockingRatio <= 70) { return 1; } else if (lockingRatio <= 80) { return 2; } else if (lockingRatio <= 90) { return 4; } else { return 8; } } /// two options to redeem from vault /// pay fee with fragment token or consume quota function getVaultQuotaFeeAtLR(uint256 lockingRatio) internal pure returns (uint32) { if (lockingRatio <= 50) { return 1; } else { return uint32(2 ** ((lockingRatio - 51) / 10 + 1)); } } function getVaultRedemptionFee(uint256 lockingRatio, uint16 baseRate) internal pure returns (uint256) { if (lockingRatio <= 50) { return FLOOR_TOKEN_AMOUNT * baseRate / 10000; } else { uint256 rate = ((lockingRatio - 51) / 10 + 2) * baseRate; return FLOOR_TOKEN_AMOUNT * rate / 10000; } } /// @return protocol fee after discount function getListingProtocolFeeWithDiscount(uint256 protocolFee, uint8 vipLevel) internal pure returns (uint256) { if (vipLevel < 3) { return protocolFee; } unchecked { /// the higher vip level, more discount for protocol fee /// discount range: 5% - 25% return protocolFee * (100 - (vipLevel - 2) * 5) / 100; } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; library Errors { /// @notice Safe Box error error SafeBoxHasExpire(); error SafeBoxNotExist(); error SafeBoxHasNotExpire(); error SafeBoxAlreadyExist(); error NoMatchingSafeBoxKey(); error SafeBoxKeyAlreadyExist(); /// @notice Auction error error AuctionHasNotCompleted(); error AuctionHasExpire(); error AuctionBidIsNotHighEnough(); error AuctionBidTokenMismatch(); error AuctionSelfBid(); error AuctionInvalidBidAmount(); error AuctionNotExist(); error SafeBoxAuctionWindowHasPassed(); /// @notice Activity common error error NftHasActiveActivities(); error ActivityHasNotCompleted(); error ActivityHasExpired(); error ActivityNotExist(); /// @notice User account error error InsufficientCredit(); error InsufficientBalanceForVipLevel(); error NoPrivilege(); /// @notice Parameter error error InvalidParam(); error NftCollectionNotSupported(); error NftCollectionAlreadySupported(); error ClaimableNftInsufficient(); error TokenNotSupported(); error PeriodQuotaExhausted(); error UserQuotaExhausted(); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import "./interface/IFlooring.sol"; import "./Constants.sol"; import { TicketRecord, SafeBoxKey, SafeBox, FeeConfig, RoyaltyFeeRate, SafeboxFeeRate, VaultFeeRate, Fees, AuctionType } from "./logic/Structs.sol"; contract FlooringGetter { IFlooring public immutable _flooring; uint256 constant COLLECTION_STATES_SLOT = 101; uint256 constant USER_ACCOUNTS_SLOT = 102; uint256 constant SUPPORTED_TOKENS_SLOT = 103; uint256 constant COLLECTION_PROXY_SLOT = 104; uint256 constant COLLECTION_FEES_SLOT = 105; uint256 constant MASK_32 = (1 << 32) - 1; uint256 constant MASK_48 = (1 << 48) - 1; uint256 constant MASK_64 = (1 << 64) - 1; uint256 constant MASK_96 = (1 << 96) - 1; uint256 constant MASK_128 = (1 << 128) - 1; uint256 constant MASK_160 = (1 << 160) - 1; constructor(address flooring) { _flooring = IFlooring(flooring); } function supportedToken(address token) public view returns (bool) { uint256 val = uint256(_flooring.extsload(keccak256(abi.encode(token, SUPPORTED_TOKENS_SLOT)))); return val != 0; } function collectionProxy(address proxy) public view returns (address) { address underlying = address(uint160(uint256(_flooring.extsload(keccak256(abi.encode(proxy, COLLECTION_PROXY_SLOT)))))); return underlying; } function collectionFee(address collection, address token) public view returns (FeeConfig memory fee) { bytes memory values = _flooring.extsload(keccak256(abi.encode(token, keccak256(abi.encode(collection, COLLECTION_FEES_SLOT)))), 3); uint256 slot1; uint256 slot2; uint256 slot3; assembly { slot1 := mload(add(values, 0x20)) slot2 := mload(add(values, 0x40)) slot3 := mload(add(values, 0x60)) } fee = FeeConfig({ royalty: RoyaltyFeeRate({ receipt: address(uint160(slot1 & MASK_160)), marketlist: uint16((slot1 >> 160) & 0xFFFF), vault: uint16((slot1 >> 176) & 0xFFFF), raffle: uint16((slot1 >> 192) & 0xFFFF) }), safeboxFee: SafeboxFeeRate({ receipt: address(uint160(slot2 & MASK_160)), auctionOwned: uint16((slot2 >> 160) & 0xFFFF), auctionExpired: uint16((slot2 >> 176) & 0xFFFF), raffle: uint16((slot2 >> 192) & 0xFFFF), marketlist: uint16((slot2 >> 208) & 0xFFFF) }), vaultFee: VaultFeeRate({ receipt: address(uint160(slot3 & MASK_160)), vaultAuction: uint16((slot3 >> 160) & 0xFFFFF), redemptionBase: uint16((slot3 >> 176) & 0xFFFFF) }) }); } function fragmentTokenOf(address collection) public view returns (address token) { bytes32 val = _flooring.extsload(keccak256(abi.encode(collection, COLLECTION_STATES_SLOT))); assembly { token := val } } function collectionInfo(address collection) public view returns ( address fragmentToken, uint256 freeNftLength, uint64 lastUpdatedBucket, uint64 nextKeyId, uint64 activeSafeBoxCnt, uint64 infiniteCnt, uint64 nextActivityId, uint32 lastVaultAuctionPeriodTs ) { bytes memory val = _flooring.extsload(keccak256(abi.encode(collection, COLLECTION_STATES_SLOT)), 9); assembly { fragmentToken := mload(add(val, 0x20)) freeNftLength := mload(add(val, mul(3, 0x20))) let cntVal := mload(add(val, mul(8, 0x20))) lastUpdatedBucket := and(cntVal, MASK_64) nextKeyId := and(shr(64, cntVal), MASK_64) activeSafeBoxCnt := and(shr(128, cntVal), MASK_64) infiniteCnt := and(shr(192, cntVal), MASK_64) cntVal := mload(add(val, mul(9, 0x20))) nextActivityId := and(cntVal, MASK_64) lastVaultAuctionPeriodTs := and(shr(64, cntVal), MASK_32) } } function getFreeNftIds(address collection, uint256 startIdx, uint256 size) public view returns (uint256[] memory nftIds) { bytes32 collectionSlot = keccak256(abi.encode(collection, COLLECTION_STATES_SLOT)); bytes32 nftIdsSlot = bytes32(uint256(collectionSlot) + 2); uint256 freeNftLength = uint256(_flooring.extsload(nftIdsSlot)); if (startIdx >= freeNftLength || size == 0) { return nftIds; } uint256 maxLen = freeNftLength - startIdx; if (size < maxLen) { maxLen = size; } bytes memory arrVal = _flooring.extsload(bytes32(uint256(keccak256(abi.encode(nftIdsSlot))) + startIdx), maxLen); nftIds = new uint256[](maxLen); assembly { for { let i := 0x20 let end := mul(add(1, maxLen), 0x20) } lt(i, end) { i := add(i, 0x20) } { mstore(add(nftIds, i), mload(add(arrVal, i))) } } } function getSafeBox(address collection, uint256 nftId) public view returns (SafeBox memory safeBox) { bytes32 collectionSlot = keccak256(abi.encode(underlyingCollection(collection), COLLECTION_STATES_SLOT)); bytes32 safeBoxMapSlot = bytes32(uint256(collectionSlot) + 3); uint256 val = uint256(_flooring.extsload(keccak256(abi.encode(nftId, safeBoxMapSlot)))); safeBox.keyId = uint64(val & MASK_64); safeBox.expiryTs = uint32(val >> 64); safeBox.owner = address(uint160(val >> 96)); } function getAuction(address collection, uint256 nftId) public view returns ( uint96 endTime, address bidToken, uint128 minimumBid, uint128 lastBidAmount, address lastBidder, address triggerAddress, uint64 activityId, AuctionType typ, Fees memory fees ) { bytes32 collectionSlot = keccak256(abi.encode(underlyingCollection(collection), COLLECTION_STATES_SLOT)); bytes32 auctionMapSlot = bytes32(uint256(collectionSlot) + 4); bytes memory val = _flooring.extsload(keccak256(abi.encode(nftId, auctionMapSlot)), 6); uint256 royaltyRate; uint256 protocolRate; assembly { let slotVal := mload(add(val, 0x20)) endTime := and(slotVal, MASK_96) bidToken := shr(96, slotVal) slotVal := mload(add(val, 0x40)) minimumBid := and(slotVal, MASK_96) triggerAddress := shr(96, slotVal) slotVal := mload(add(val, 0x60)) lastBidAmount := and(slotVal, MASK_96) lastBidder := shr(96, slotVal) slotVal := mload(add(val, 0x80)) activityId := and(shr(8, slotVal), MASK_64) typ := and(shr(104, slotVal), 0xFF) royaltyRate := mload(add(val, 0xA0)) protocolRate := mload(add(val, 0xC0)) } fees = parseFees(royaltyRate, protocolRate); } function getRaffle(address collection, uint256 nftId) public view returns ( uint48 endTime, uint48 maxTickets, address token, uint96 ticketPrice, uint96 collectedFund, uint64 activityId, address owner, uint48 ticketSold, bool isSettling, uint256 ticketsArrLen, Fees memory fees ) { bytes32 raffleMapSlot = bytes32(uint256(keccak256(abi.encode(underlyingCollection(collection), COLLECTION_STATES_SLOT))) + 5); bytes memory val = _flooring.extsload(keccak256(abi.encode(nftId, raffleMapSlot)), 6); uint256 royaltyRate; uint256 protocolRate; assembly { let slotVal := mload(add(val, 0x20)) endTime := and(slotVal, MASK_48) maxTickets := and(shr(48, slotVal), MASK_48) token := and(shr(96, slotVal), MASK_160) slotVal := mload(add(val, 0x40)) owner := and(slotVal, MASK_160) ticketPrice := and(shr(160, slotVal), MASK_96) slotVal := mload(add(val, 0x60)) activityId := and(slotVal, MASK_64) collectedFund := and(shr(64, slotVal), MASK_96) ticketSold := and(shr(160, slotVal), MASK_48) isSettling := and(shr(208, slotVal), 0xFF) ticketsArrLen := mload(add(val, 0x80)) royaltyRate := mload(add(val, 0xA0)) protocolRate := mload(add(val, 0xC0)) } fees = parseFees(royaltyRate, protocolRate); } function getRaffleTicketRecords(address collection, uint256 nftId, uint256 startIdx, uint256 size) public view returns (TicketRecord[] memory tickets) { bytes32 collectionSlot = keccak256(abi.encode(underlyingCollection(collection), COLLECTION_STATES_SLOT)); bytes32 raffleMapSlot = bytes32(uint256(collectionSlot) + 5); bytes32 ticketRecordsSlot = bytes32(uint256(keccak256(abi.encode(nftId, raffleMapSlot))) + 3); uint256 totalRecordsLen = uint256(_flooring.extsload(ticketRecordsSlot)); if (startIdx >= totalRecordsLen || size == 0) { return tickets; } uint256 maxLen = totalRecordsLen - startIdx; if (size < maxLen) { maxLen = size; } bytes memory arrVal = _flooring.extsload(bytes32(uint256(keccak256(abi.encode(ticketRecordsSlot))) + startIdx), maxLen); tickets = new TicketRecord[](maxLen); for (uint256 i; i < maxLen; ++i) { uint256 element; assembly { element := mload(add(arrVal, mul(add(i, 1), 0x20))) } tickets[i].buyer = address(uint160(element & MASK_160)); tickets[i].startIdx = uint48((element >> 160) & MASK_48); tickets[i].endIdx = uint48((element >> 208) & MASK_48); } } function getPrivateOffer(address collection, uint256 nftId) public view returns ( uint96 endTime, address token, uint96 price, address owner, address buyer, uint64 activityId, Fees memory fees ) { bytes32 collectionSlot = keccak256(abi.encode(underlyingCollection(collection), COLLECTION_STATES_SLOT)); bytes32 offerMapSlot = bytes32(uint256(collectionSlot) + 6); bytes memory val = _flooring.extsload(keccak256(abi.encode(nftId, offerMapSlot)), 5); uint256 royaltyRate; uint256 protocolRate; assembly { let slotVal := mload(add(val, 0x20)) endTime := and(slotVal, MASK_96) token := and(shr(96, slotVal), MASK_160) slotVal := mload(add(val, 0x40)) price := and(slotVal, MASK_96) owner := and(shr(96, slotVal), MASK_160) slotVal := mload(add(val, 0x60)) buyer := and(slotVal, MASK_160) activityId := and(shr(160, slotVal), MASK_64) royaltyRate := mload(add(val, 0x80)) protocolRate := mload(add(val, 0xA0)) } fees = parseFees(royaltyRate, protocolRate); } function tokenBalance(address user, address token) public view returns (uint256) { bytes32 userSlot = keccak256(abi.encode(user, USER_ACCOUNTS_SLOT)); bytes32 tokenMapSlot = bytes32(uint256(userSlot) + 4); bytes32 balance = _flooring.extsload(keccak256(abi.encode(token, tokenMapSlot))); return uint256(balance); } function userAccount(address user) public view returns ( uint256 minMaintCredit, address firstCollection, uint8 minMaintVipLevel, uint256[] memory vipKeyCnts, uint256 lockedCredit, uint32 lastQuotaPeriodTs, uint16 safeboxQuotaUsed ) { bytes32 userSlot = keccak256(abi.encode(user, USER_ACCOUNTS_SLOT)); bytes memory val = _flooring.extsload(userSlot, 6); uint256 vipInfo; assembly { let slotVal := mload(add(val, 0x20)) minMaintCredit := and(slotVal, MASK_96) firstCollection := and(shr(96, slotVal), MASK_160) vipInfo := mload(add(val, 0x40)) lockedCredit := mload(add(val, 0x60)) slotVal := mload(add(val, 0xC0)) lastQuotaPeriodTs := and(slotVal, MASK_32) safeboxQuotaUsed := and(shr(32, slotVal), 0xFFFF) } vipKeyCnts = new uint256[](Constants.VIP_LEVEL_COUNT); minMaintVipLevel = uint8((vipInfo >> 240) & 0xFF); for (uint256 i; i < Constants.VIP_LEVEL_COUNT; ++i) { vipKeyCnts[i] = (vipInfo >> (i * 24)) & 0xFFFFFF; } } function userCollection(address user, address collection, uint256 nftId) public view returns ( uint256 totalLockingCredit, address next, uint32 keyCnt, uint32 vaultContQuota, uint32 lastVaultActiveTs, SafeBoxKey memory key ) { bytes32 userSlot = keccak256(abi.encode(user, USER_ACCOUNTS_SLOT)); bytes32 collectionSlot = keccak256(abi.encode(underlyingCollection(collection), bytes32(uint256(userSlot) + 3))); bytes32 collectionKeysSlot = keccak256(abi.encode(nftId, collectionSlot)); bytes memory vals = _flooring.extsload(bytes32(uint256(collectionSlot) + 1), 2); assembly { let slotVal := mload(add(vals, 0x20)) totalLockingCredit := and(slotVal, MASK_96) next := and(shr(96, slotVal), MASK_160) slotVal := mload(add(vals, 0x40)) keyCnt := and(slotVal, MASK_32) vaultContQuota := and(shr(32, slotVal), MASK_32) lastVaultActiveTs := and(shr(64, slotVal), MASK_32) } { uint256 val = uint256(_flooring.extsload(collectionKeysSlot)); key.lockingCredit = uint96(val & MASK_96); key.keyId = uint64((val >> 96) & MASK_64); key.vipLevel = uint8((val >> 160) & 0xFF); } } function underlyingCollection(address collection) private view returns (address) { address underlying = collectionProxy(collection); if (underlying == address(0)) { return collection; } return underlying; } function parseFees(uint256 royalty, uint256 protocol) private pure returns (Fees memory fees) { fees.royalty.receipt = address(uint160(royalty & MASK_160)); fees.royalty.rateBips = uint16(royalty >> 160); fees.protocol.receipt = address(uint160(protocol & MASK_160)); fees.protocol.rateBips = uint16(protocol >> 160); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "./IMulticall.sol"; interface IFlooring is IERC721Receiver, IMulticall { /// Admin Operations /// @notice Add new collection for Flooring Protocol function supportNewCollection(address _originalNFT, address fragmentToken) external payable; /// @notice Add new token which will be used as settlement token in Flooring Protocol /// @param addOrRemove `true` means add token, `false` means remove token function supportNewToken(address _tokenAddress, bool addOrRemove) external payable; /// @notice set proxy collection config /// Note. the `tokenId`s of the proxy collection and underlying collection must be correspond one by one /// eg. Paraspace Derivative Token BAYC(nBAYC) -> BAYC function setCollectionProxy(address proxyCollection, address underlyingCollection) external payable; /// @notice withdraw platform fee accumulated. /// Note. withdraw from `address(this)`'s account. function withdrawPlatformFee(address token, uint256 amount) external payable; /// @notice Deposit and lock credit token on behalf of receiver /// user can not withdraw these tokens until `unlockCredit` is called. function addAndLockCredit(address receiver, uint256 amount) external payable; /// @notice Unlock user credit token to allow withdraw /// used to release investors' funds as time goes /// Note. locked credit can be used to operate safeboxes(lock/unlock...) function unlockCredit(address receiver, uint256 amount) external payable; /// User Operations /// @notice User deposits token to the Floor Contract /// @param onBehalfOf deposit token into `onBehalfOf`'s account.(note. the tokens of msg.sender will be transfered) function addTokens(address onBehalfOf, address token, uint256 amount) external payable; /// @notice User removes token from Floor Contract /// @param receiver who will receive the funds.(note. the token of msg.sender will be transfered) function removeTokens(address token, uint256 amount, address receiver) external; /// @notice Lock specified `nftIds` into Flooring Safeboxes and receive corresponding Fragment Tokens of the `collection` /// @param expiryTs when the safeboxes expired, `0` means infinite lock without expiry /// @param vipLevel vip tier required in this lock operation /// @param maxCredit maximum credit can be locked in this operation, if real cost exceeds this limit, the tx will fail /// @param onBehalfOf who will receive the safebox and fragment tokens.(note. the NFTs of the msg.sender will be transfered) function lockNFTs( address collection, uint256[] memory nftIds, uint256 expiryTs, uint256 vipLevel, uint256 maxCredit, address onBehalfOf ) external returns (uint256); /// @notice Extend the exist safeboxes with longer lock duration with more credit token staked /// @param expiryTs new expiry timestamp, should bigger than previous expiry function extendKeys( address collection, uint256[] memory nftIds, uint256 expiryTs, uint256 vipLevel, uint256 maxCredit ) external returns (uint256); /// @notice Unlock specified `nftIds` which had been locked previously /// sender's wallet should have enough Fragment Tokens of the `collection` which will be burned to redeem the NFTs /// @param expiryTs the latest nft's expiry, we need this to clear locking records /// if the value smaller than the latest nft's expiry, the tx will fail /// if part of `nftIds` were locked infinitely, just skip these expiry /// @param receiver who will receive the NFTs. /// note. - The safeboxes of the msg.sender will be removed. /// - The Fragment Tokens of the msg.sender will be burned. function unlockNFTs(address collection, uint256 expiryTs, uint256[] memory nftIds, address receiver) external; /// @notice Fragment specified `nftIds` into Floor Vault and receive Fragment Tokens without any locking /// after fragmented, any one has enough Fragment Tokens can redeem there `nftIds` /// @param onBehalfOf who will receive the fragment tokens and the vault contribution quota.(note. the NFTs of the msg.sender will be transfered) /// if onBehalfOf == address(this), it means msg.sender intends to swap the same quantity of NFTs from the vault as the `nftIds` function fragmentNFTs(address collection, uint256[] memory nftIds, address onBehalfOf) external; /// @notice Kick expired safeboxes to the vault function tidyExpiredNFTs(address collection, uint256[] memory nftIds) external; /// @notice Randomly claim `claimCnt` NFTs from Floor Vault /// sender's wallet should have enough Fragment Tokens of the `collection` which will be burned to redeem the NFTs /// @param maxCredit maximum credit can be costed in this operation, if real cost exceeds this limit, the tx will fail /// @param receiver who will receive the NFTs. /// note. - the msg.sender will pay the redemption cost. /// - The Fragment Tokens of the msg.sender will be burned. function claimRandomNFT(address collection, uint256 claimCnt, uint256 maxCredit, address receiver) external returns (uint256); /// @notice Start auctions on specified `nftIds` with an initial bid price(`bidAmount`) /// This kind of auctions will be settled with Floor Credit Token /// @param bidAmount initial bid price function initAuctionOnExpiredSafeBoxes( address collection, uint256[] memory nftIds, address bidToken, uint256 bidAmount ) external; /// @notice Start auctions on specified `nftIds` index in the vault with an initial bid price(`bidAmount`) /// This kind of auctions will be settled with Fragment Token of the collection /// @param bidAmount initial bid price function initAuctionOnVault(address collection, uint256[] memory vaultIdx, address bidToken, uint96 bidAmount) external; /// @notice Owner starts auctions on his locked Safeboxes /// @param maxExpiry the latest nft's expiry, we need this to clear locking records /// @param token which token should be used to settle auctions(bid, settle) /// @param minimumBid minimum bid price when someone place a bid on the auction function ownerInitAuctions( address collection, uint256[] memory nftIds, uint256 maxExpiry, address token, uint256 minimumBid ) external; /// @notice Place a bid on specified `nftId`'s action /// @param bidAmount bid price /// @param bidOptionIdx which option used to extend auction expiry and bid price function placeBidOnAuction(address collection, uint256 nftId, uint256 bidAmount, uint256 bidOptionIdx) external payable; /// @notice Settle auctions of `nftIds` function settleAuctions(address collection, uint256[] memory nftIds) external; struct RaffleInitParam { address collection; uint256[] nftIds; /// @notice which token used to buy and settle raffle address ticketToken; /// @notice price per ticket uint96 ticketPrice; /// @notice max tickets amount can be sold uint32 maxTickets; /// @notice durationIdx used to get how long does raffles last uint256 duration; /// @notice the largest epxiry of nfts, we need this to clear locking records uint256 maxExpiry; } /// @notice Owner start raffles on locked `nftIds` function ownerInitRaffles(RaffleInitParam memory param) external; /// @notice Buy `nftId`'s raffle tickets /// @param ticketCnt how many tickets should be bought in this operation function buyRaffleTickets(address collectionId, uint256 nftId, uint256 ticketCnt) external payable; /// @notice Settle raffles of `nftIds` function settleRaffles(address collectionId, uint256[] memory nftIds) external; struct PrivateOfferInitParam { address collection; uint256[] nftIds; /// @notice the largest epxiry of nfts, we need this to clear locking records uint256 maxExpiry; /// @notice who will receive the otc offers address receiver; /// @notice which token used to settle offers address token; /// @notice price of the offers uint96 price; } /// @notice Owner start private offers(otc) on locked `nftIds` function ownerInitPrivateOffers(PrivateOfferInitParam memory param) external; enum OfferOpType { Cancel, Decline, ChangePrice } struct ChangeOfferPriceData { uint96[] priceList; } /// @notice Owner or Receiver cancel the private offers of `nftIds` function modifyOffers(address collectionId, uint256[] memory nftIds, OfferOpType opTy, bytes calldata data) external; /// @notice Receiver accept the private offers of `nftIds` function buyerAcceptPrivateOffers(address collectionId, uint256[] memory nftIds, uint256 maxSafeboxExpiry) external payable; /// @notice Clear expired or mismatching safeboxes of `nftIds` in user account /// @param onBehalfOf whose account will be recalculated /// @return credit amount has been released function removeExpiredKeyAndRestoreCredit( address collection, uint256[] memory nftIds, address onBehalfOf, bool verifyLocking ) external returns (uint256); /// @notice Update user's staking credit status by iterating all active collections in user account /// @param onBehalfOf whose account will be recalculated /// @return availableCredit how many credit available to use after this opeartion function recalculateAvailableCredit(address onBehalfOf) external returns (uint256 availableCredit); /// Util operations /// @notice Called by external contracts to access granular pool state /// @param slot Key of slot to sload /// @return value The value of the slot as bytes32 function extsload(bytes32 slot) external view returns (bytes32 value); /// @notice Called by external contracts to access granular pool state /// @param slot Key of slot to start sloading from /// @param nSlots Number of slots to load into return value /// @return value The value of the sload-ed slots concatenated as dynamic bytes function extsload(bytes32 slot, uint256 nSlots) external view returns (bytes memory value); function creditToken() external view returns (address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; interface IFragmentToken { error CallerIsNotTrustedContract(); function mint(address account, uint256 amount) external; function burn(address account, uint256 amount) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; /// @title Multicall interface /// @notice Enables calling multiple methods in a single call to the contract interface IMulticall { /** * @dev A call to an address target failed. The target may have reverted. */ error FailedMulticall(); struct CallData { address target; bytes callData; } /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes[] calldata data) external returns (bytes[] memory results); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title Interface for WETH9 interface IWETH9 is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; library CurrencyTransfer { /// @notice Thrown when an ERC20 transfer fails error ERC20TransferFailed(); /// @notice Thrown when an NATIVE transfer fails error NativeTransferFailed(); address public constant NATIVE = address(0); function safeTransfer(address token, address to, uint256 amount) internal { // ref // https://docs.soliditylang.org/en/latest/internals/layout_in_memory.html // implementation from // https://github.com/transmissions11/solmate/blob/v7/src/utils/SafeTransferLib.sol // https://github.com/Uniswap/v4-core/blob/main/contracts/types/Currency.sol bool success; if (token == NATIVE) { assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } if (!success) revert NativeTransferFailed(); } else { /// @solidity memory-safe-assembly assembly { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(4, to) // Append the "to" argument. mstore(36, amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because that's the total length of our calldata (4 + 32 * 2) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. call(gas(), token, 0, 0, 68, 0, 32) ) mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, memPointer) // Restore the memPointer. } if (!success) revert ERC20TransferFailed(); } } function safeTransferFrom(address token, address from, address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(4, from) // Append and mask the "from" argument. mstore(36, to) // Append and mask the "to" argument. // Append the "amount" argument. Masking not required as it's a full 32 byte type. mstore(68, amount) success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, 0, 100, 0, 32) ) mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, memPointer) // Restore the memPointer. } if (!success) revert ERC20TransferFailed(); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; library ERC721Transfer { /// @notice Thrown when an ERC721 transfer fails error ERC721TransferFailed(); function safeTransferFrom(address collection, address from, address to, uint256 tokenId) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0, 0x42842e0e00000000000000000000000000000000000000000000000000000000) mstore(4, from) // Append and mask the "from" argument. mstore(36, to) // Append and mask the "to" argument. // Append the "tokenId" argument. Masking not required as it's a full 32 byte type. mstore(68, tokenId) success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), collection, 0, 0, 100, 0, 32) ) mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, memPointer) // Restore the memPointer. } if (!success) revert ERC721TransferFailed(); } function safeBatchTransferFrom(address collection, address from, address to, uint256[] memory tokenIds) internal { unchecked { uint256 len = tokenIds.length; for (uint256 i; i < len; ++i) { safeTransferFrom(collection, from, to, tokenIds[i]); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; /// @notice Simple single owner authorization mixin. /// @author modified from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol) abstract contract OwnedUpgradeable { error Unauthorized(); event OwnerUpdated(address indexed user, address indexed newOwner); address public owner; modifier onlyOwner() virtual { checkOwner(); _; } function checkOwner() internal view { if (msg.sender != owner) revert Unauthorized(); } function __Owned_init() internal { owner = msg.sender; } function setOwner(address newOwner) public virtual onlyOwner { owner = newOwner; emit OwnerUpdated(msg.sender, newOwner); } uint256[49] private __gap; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import {SafeBox, SafeBoxKey} from "./Structs.sol"; library SafeBoxLib { uint64 public constant SAFEBOX_KEY_NOTATION = type(uint64).max; function isInfiniteSafeBox(SafeBox storage safeBox) internal view returns (bool) { return safeBox.expiryTs == 0; } function isSafeBoxExpired(SafeBox storage safeBox) internal view returns (bool) { return safeBox.expiryTs != 0 && safeBox.expiryTs < block.timestamp; } function _isSafeBoxExpired(SafeBox memory safeBox) internal view returns (bool) { return safeBox.expiryTs != 0 && safeBox.expiryTs < block.timestamp; } function isKeyMatchingSafeBox(SafeBox storage safeBox, SafeBoxKey storage safeBoxKey) internal view returns (bool) { return safeBox.keyId == safeBoxKey.keyId; } function _isKeyMatchingSafeBox(SafeBox memory safeBox, SafeBoxKey memory safeBoxKey) internal pure returns (bool) { return safeBox.keyId == safeBoxKey.keyId; } function encodeSafeBoxKey(SafeBoxKey memory key) internal pure returns (uint256) { uint256 val = key.lockingCredit; val |= (uint256(key.keyId) << 96); val |= (uint256(key.vipLevel) << 160); return val; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import "../interface/IFragmentToken.sol"; struct SafeBox { /// Either matching a key OR Constants.SAFEBOX_KEY_NOTATION meaning temporarily /// held by a bidder in auction. uint64 keyId; /// The timestamp that the safe box expires. uint32 expiryTs; /// The owner of the safebox. It maybe outdated due to expiry address owner; } struct PrivateOffer { /// private offer end time uint96 endTime; /// which token used to accpet the offer address token; /// price of the offer uint96 price; address owner; /// who should receive the offer address buyer; uint64 activityId; Fees fees; } enum AuctionType { Owned, Expired, Vault } struct AuctionInfo { /// The end time for the auction. uint96 endTime; /// Bid token address. address bidTokenAddress; /// Minimum Bid. uint96 minimumBid; /// The person who trigger the auction at the beginning. address triggerAddress; uint96 lastBidAmount; address lastBidder; /// [Deprecated] Whether the auction is triggered by the NFT owner itself? /// Note. Don't remove it directly as we need keep mainnet contract layout bool isSelfTriggered; uint64 activityId; /// [Deprecated] fee config /// Note. Don't remove it directly as we need keep mainnet contract layout uint32 oldFeeRateBips; AuctionType typ; Fees fees; } struct TicketRecord { /// who buy the tickets address buyer; /// Start index of tickets /// [startIdx, endIdx) uint48 startIdx; /// End index of tickets uint48 endIdx; } struct RaffleInfo { /// raffle end time uint48 endTime; /// max tickets amount the raffle can sell uint48 maxTickets; /// which token used to buy the raffle tickets address token; /// owner of raffle address owner; /// price per ticket uint96 ticketPrice; uint64 activityId; /// total funds collected by selling tickets uint96 collectedFund; /// total sold tickets amount uint48 ticketSold; /// whether the raffle is being settling bool isSettling; /// tickets sold records TicketRecord[] tickets; Fees fees; } struct CollectionState { /// The address of the Floor Token cooresponding to the NFTs. IFragmentToken floorToken; /// Records the active safe box in each time bucket. mapping(uint256 => uint256) countingBuckets; /// Stores all of the NFTs that has been fragmented but *without* locked up limit. uint256[] freeTokenIds; /// Huge map for all the `SafeBox`es in one collection. mapping(uint256 => SafeBox) safeBoxes; /// Stores all the ongoing auctions: nftId => `AuctionInfo`. mapping(uint256 => AuctionInfo) activeAuctions; /// Stores all the ongoing raffles: nftId => `RaffleInfo`. mapping(uint256 => RaffleInfo) activeRaffles; /// Stores all the ongoing private offers: nftId => `PrivateOffer`. mapping(uint256 => PrivateOffer) activePrivateOffers; /// The last bucket time the `countingBuckets` is updated. uint64 lastUpdatedBucket; /// Next Key Id. This should start from 1, we treat key id `SafeboxLib.SAFEBOX_KEY_NOTATION` as temporarily /// being used for activities(auction/raffle). uint64 nextKeyId; /// Active Safe Box Count. uint64 activeSafeBoxCnt; /// The number of infinite lock count. uint64 infiniteCnt; /// Next Activity Id. This should start from 1 uint64 nextActivityId; uint32 lastVaultAuctionPeriodTs; } struct UserFloorAccount { /// @notice it should be maximum of the `totalLockingCredit` across all collections uint96 minMaintCredit; /// @notice used to iterate collection accounts /// packed with `minMaintCredit` to reduce storage slot access address firstCollection; /// @notice user vip level related info /// 0 - 239 bits: store SafeBoxKey Count per vip level, per level using 24 bits /// 240 - 247 bits: store minMaintVipLevel /// 248 - 255 bits: remaining uint256 vipInfo; /// @notice Locked Credit amount which cannot be withdrawn and will be released as time goes. uint256 lockedCredit; mapping(address => CollectionAccount) accounts; mapping(address => uint256) tokenAmounts; /// Each account has safebox quota to use per period uint32 lastQuotaPeriodTs; uint16 safeboxQuotaUsed; /// [Deprecated] Each account has vault redemption waiver per period uint32 lastWaiverPeriodTs; uint96 creditWaiverUsed; } struct SafeBoxKey { /// locked credit amount of this safebox uint96 lockingCredit; /// corresponding key id of the safebox uint64 keyId; /// which vip level the safebox locked uint8 vipLevel; } struct CollectionAccount { mapping(uint256 => SafeBoxKey) keys; /// total locking credit of all `keys` in this collection uint96 totalLockingCredit; /// track next collection as linked list address next; /// tracking total locked of the collection uint32 keyCnt; /// Depositing to vault gets quota, redepmtion consumes quota uint32 vaultContQuota; /// Used to track and clear vault contribution quota when the quota is inactive for a certain duration uint32 lastVaultActiveTs; } struct Fees { FeeRate royalty; FeeRate protocol; } struct FeeConfig { RoyaltyFeeRate royalty; SafeboxFeeRate safeboxFee; VaultFeeRate vaultFee; } struct RoyaltyFeeRate { address receipt; uint16 marketlist; uint16 vault; uint16 raffle; } struct VaultFeeRate { address receipt; uint16 vaultAuction; uint16 redemptionBase; } struct SafeboxFeeRate { address receipt; uint16 auctionOwned; uint16 auctionExpired; uint16 raffle; uint16 marketlist; } struct FeeRate { address receipt; uint16 rateBips; } /// Internal Structure struct LockParam { address proxyCollection; address collection; uint256[] nftIds; uint256 expiryTs; uint8 vipLevel; uint256 maxCreditCost; address creditToken; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.20; import "./interface/IMulticall.sol"; /// @title Multicall /// @notice Enables calling multiple methods in a single call to the contract abstract contract Multicall is IMulticall { /// @inheritdoc IMulticall function multicall(bytes[] calldata data) external virtual override returns (bytes[] memory) { bytes[] memory results = new bytes[](data.length); for (uint256 i; i < data.length;) { /// @custom:oz-upgrades-unsafe-allow-reachable delegatecall (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (success) { results[i] = result; } else { // Next 4 lines from // https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/AddressUpgradeable.sol#L229 if (result.length > 0) { assembly { let returndata_size := mload(result) revert(add(32, result), returndata_size) } } else { revert FailedMulticall(); } } unchecked { ++i; } } return results; } }
{ "metadata": { "bytecodeHash": "none", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 800 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"flooring","type":"address"},{"internalType":"address","name":"uniswapV3Router","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"ERC20TransferFailed","type":"error"},{"inputs":[],"name":"ERC721TransferFailed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"FailedMulticall","type":"error"},{"inputs":[],"name":"InsufficientWETH9","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NotRouterOrWETH9","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_flooring","outputs":[{"internalType":"contract IFlooring","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"claimCnt","type":"uint256"},{"internalType":"uint256","name":"maxCostToClaim","type":"uint256"},{"internalType":"address","name":"swapTokenIn","type":"address"},{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct ISwapRouter.ExactOutputParams","name":"swapParam","type":"tuple"}],"name":"buyAndClaimExpired","outputs":[{"internalType":"uint256","name":"tokenCost","type":"uint256"},{"internalType":"uint256","name":"claimCost","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"claimCnt","type":"uint256"},{"internalType":"uint256","name":"maxCostToClaim","type":"uint256"},{"internalType":"address","name":"swapTokenIn","type":"address"},{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct ISwapRouter.ExactOutputParams","name":"swapParam","type":"tuple"}],"name":"buyAndClaimVault","outputs":[{"internalType":"uint256","name":"tokenCost","type":"uint256"},{"internalType":"uint256","name":"claimCost","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"collectionFee","outputs":[{"components":[{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"marketlist","type":"uint16"},{"internalType":"uint16","name":"vault","type":"uint16"},{"internalType":"uint16","name":"raffle","type":"uint16"}],"internalType":"struct RoyaltyFeeRate","name":"royalty","type":"tuple"},{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"auctionOwned","type":"uint16"},{"internalType":"uint16","name":"auctionExpired","type":"uint16"},{"internalType":"uint16","name":"raffle","type":"uint16"},{"internalType":"uint16","name":"marketlist","type":"uint16"}],"internalType":"struct SafeboxFeeRate","name":"safeboxFee","type":"tuple"},{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"vaultAuction","type":"uint16"},{"internalType":"uint16","name":"redemptionBase","type":"uint16"}],"internalType":"struct VaultFeeRate","name":"vaultFee","type":"tuple"}],"internalType":"struct FeeConfig","name":"fee","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"collectionInfo","outputs":[{"internalType":"address","name":"fragmentToken","type":"address"},{"internalType":"uint256","name":"freeNftLength","type":"uint256"},{"internalType":"uint64","name":"lastUpdatedBucket","type":"uint64"},{"internalType":"uint64","name":"nextKeyId","type":"uint64"},{"internalType":"uint64","name":"activeSafeBoxCnt","type":"uint64"},{"internalType":"uint64","name":"infiniteCnt","type":"uint64"},{"internalType":"uint64","name":"nextActivityId","type":"uint64"},{"internalType":"uint32","name":"lastVaultAuctionPeriodTs","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxy","type":"address"}],"name":"collectionProxy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bool","name":"unwrapWETH","type":"bool"},{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"internalType":"struct ISwapRouter.ExactInputParams","name":"swapParam","type":"tuple"}],"name":"fragmentAndSell","outputs":[{"internalType":"uint256","name":"swapOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"}],"name":"fragmentTokenOf","outputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getAuction","outputs":[{"internalType":"uint96","name":"endTime","type":"uint96"},{"internalType":"address","name":"bidToken","type":"address"},{"internalType":"uint128","name":"minimumBid","type":"uint128"},{"internalType":"uint128","name":"lastBidAmount","type":"uint128"},{"internalType":"address","name":"lastBidder","type":"address"},{"internalType":"address","name":"triggerAddress","type":"address"},{"internalType":"uint64","name":"activityId","type":"uint64"},{"internalType":"enum AuctionType","name":"typ","type":"uint8"},{"components":[{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"rateBips","type":"uint16"}],"internalType":"struct FeeRate","name":"royalty","type":"tuple"},{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"rateBips","type":"uint16"}],"internalType":"struct FeeRate","name":"protocol","type":"tuple"}],"internalType":"struct Fees","name":"fees","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"startIdx","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"getFreeNftIds","outputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getPrivateOffer","outputs":[{"internalType":"uint96","name":"endTime","type":"uint96"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"uint64","name":"activityId","type":"uint64"},{"components":[{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"rateBips","type":"uint16"}],"internalType":"struct FeeRate","name":"royalty","type":"tuple"},{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"rateBips","type":"uint16"}],"internalType":"struct FeeRate","name":"protocol","type":"tuple"}],"internalType":"struct Fees","name":"fees","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getRaffle","outputs":[{"internalType":"uint48","name":"endTime","type":"uint48"},{"internalType":"uint48","name":"maxTickets","type":"uint48"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint96","name":"ticketPrice","type":"uint96"},{"internalType":"uint96","name":"collectedFund","type":"uint96"},{"internalType":"uint64","name":"activityId","type":"uint64"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint48","name":"ticketSold","type":"uint48"},{"internalType":"bool","name":"isSettling","type":"bool"},{"internalType":"uint256","name":"ticketsArrLen","type":"uint256"},{"components":[{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"rateBips","type":"uint16"}],"internalType":"struct FeeRate","name":"royalty","type":"tuple"},{"components":[{"internalType":"address","name":"receipt","type":"address"},{"internalType":"uint16","name":"rateBips","type":"uint16"}],"internalType":"struct FeeRate","name":"protocol","type":"tuple"}],"internalType":"struct Fees","name":"fees","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"startIdx","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"getRaffleTicketRecords","outputs":[{"components":[{"internalType":"address","name":"buyer","type":"address"},{"internalType":"uint48","name":"startIdx","type":"uint48"},{"internalType":"uint48","name":"endIdx","type":"uint48"}],"internalType":"struct TicketRecord[]","name":"tickets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getSafeBox","outputs":[{"components":[{"internalType":"uint64","name":"keyId","type":"uint64"},{"internalType":"uint32","name":"expiryTs","type":"uint32"},{"internalType":"address","name":"owner","type":"address"}],"internalType":"struct SafeBox","name":"safeBox","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"supportedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"unwrapWETH9","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userAccount","outputs":[{"internalType":"uint256","name":"minMaintCredit","type":"uint256"},{"internalType":"address","name":"firstCollection","type":"address"},{"internalType":"uint8","name":"minMaintVipLevel","type":"uint8"},{"internalType":"uint256[]","name":"vipKeyCnts","type":"uint256[]"},{"internalType":"uint256","name":"lockedCredit","type":"uint256"},{"internalType":"uint32","name":"lastQuotaPeriodTs","type":"uint32"},{"internalType":"uint16","name":"safeboxQuotaUsed","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"collection","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"userCollection","outputs":[{"internalType":"uint256","name":"totalLockingCredit","type":"uint256"},{"internalType":"address","name":"next","type":"address"},{"internalType":"uint32","name":"keyCnt","type":"uint32"},{"internalType":"uint32","name":"vaultContQuota","type":"uint32"},{"internalType":"uint32","name":"lastVaultActiveTs","type":"uint32"},{"components":[{"internalType":"uint96","name":"lockingCredit","type":"uint96"},{"internalType":"uint64","name":"keyId","type":"uint64"},{"internalType":"uint8","name":"vipLevel","type":"uint8"}],"internalType":"struct SafeBoxKey","name":"key","type":"tuple"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61010060408190523060a05262004275388190039081908339810160408190526200002a9162000064565b6001600160a01b0392831660805290821660c0521660e052620000ab565b80516001600160a01b03811681146200005f575f80fd5b919050565b5f805f6060848603121562000077575f80fd5b620000828462000048565b9250620000926020850162000048565b9150620000a26040850162000048565b90509250925092565b60805160a05160c05160e05161409a620001db5f395f8181610201015281816105770152818161116b0152818161121b0152612f8d01525f81816101cd0152818161064501528181611e990152818161200601528181612ff10152818161306b015281816130f5015261314501525f8181612b9c01528181612bc50152612d3201525f8181610519015281816108cf01528181610a0c01528181610c0201528181610ce701528181610e33015281816110670152818161133e01528181611561015281816116340152818161171f015281816118eb01528181611b2301528181611bcb01528181611e6f01528181611f120152818161213e015281816121e701528181612435015281816124bd01528181612548015281816125d90152818161271a01526128e9015261409a5ff3fe6080604052600436106101bd575f3560e01c8063725d33b0116100f2578063ac9650d811610092578063deefbf8711610062578063deefbf87146107e1578063e2c6e438146107f4578063ea5eda3214610823578063ef2d242714610855575f80fd5b8063ac9650d814610721578063ad3cb1cc1461074d578063c660093d146107a2578063c999b80e146107b5575f80fd5b806376c90757116100cd57806376c907571461069b5780638129fc1c146106c3578063824d3575146106d75780638da5cb5b14610703575f80fd5b8063725d33b014610615578063735de9f714610634578063762a66a214610667575f80fd5b80633c777f411161015d5780634f1ef286116101385780634f1ef286146105995780634f67caa7146105ac57806352d1902d146105e25780635818ea1c146105f6575f80fd5b80633c777f411461050857806349404b7c146105535780634aa4a4fc14610566575f80fd5b80631f0c602d116101985780631f0c602d146102dd57806321dfa77b1461035957806329e81d71146103e3578063316d1a21146104ae575f80fd5b80631049334f1461024857806313af40351461027a578063150b7a0214610299575f80fd5b3661024457336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015906102245750336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614155b1561024257604051639f5c13f160e01b815260040160405180910390fd5b005b5f80fd5b348015610253575f80fd5b506102676102623660046134ea565b610887565b6040519081526020015b60405180910390f35b348015610285575f80fd5b5061024261029436600461351b565b6109a2565b3480156102a4575f80fd5b506102c46102b3366004613534565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610271565b3480156102e8575f80fd5b506102fc6102f736600461351b565b610a01565b604080516001600160a01b039099168952602089019790975267ffffffffffffffff9586169688019690965292841660608701529083166080860152821660a08501521660c083015263ffffffff1660e082015261010001610271565b348015610364575f80fd5b506103786103733660046135c7565b610b33565b604080519687526001600160a01b0390951660208088019190915263ffffffff9485168787015292841660608701529216608085015281516001600160601b031660a085015281015167ffffffffffffffff1660c0840152015160ff1660e082015261010001610271565b3480156103ee575f80fd5b506104026103fd3660046134ea565b610db3565b6040516102719190815180516001600160a01b03908116835260208083015161ffff90811682860152604080850151821681870152606094850151821685870152828701518051851660808089019190915281850151841660a089015281830151841660c089015295810151831660e088015294909401518116610100860152948301518051909216610120850152810151841661014084015201519091166101608201526101800190565b3480156104b9575f80fd5b506104cd6104c8366004613600565b610ff8565b60408051825167ffffffffffffffff16815260208084015163ffffffff1690820152918101516001600160a01b031690820152606001610271565b348015610513575f80fd5b5061053b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610271565b610242610561366004613628565b611154565b348015610571575f80fd5b5061053b7f000000000000000000000000000000000000000000000000000000000000000081565b6102426105a7366004613707565b61128a565b3480156105b7575f80fd5b506105cb6105c6366004613600565b6112a9565b6040516102719b9a99989796959493929190613798565b3480156105ed575f80fd5b5061026761152f565b348015610601575f80fd5b5061053b61061036600461351b565b61155d565b348015610620575f80fd5b5061053b61062f36600461351b565b611630565b34801561063f575f80fd5b5061053b7f000000000000000000000000000000000000000000000000000000000000000081565b348015610672575f80fd5b50610686610681366004613600565b611689565b60405161027199989796959493929190613825565b6106ae6106a936600461399c565b6118e7565b60408051928352602083019190915201610271565b3480156106ce575f80fd5b50610242611983565b3480156106e2575f80fd5b506106f66106f1366004613a36565b611ac6565b6040516102719190613a9f565b34801561070e575f80fd5b505f5461053b906001600160a01b031681565b34801561072c575f80fd5b5061074061073b366004613ab1565b611d0e565b6040516102719190613b3d565b348015610758575f80fd5b506107956040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102719190613b9d565b6102676107b0366004613bbc565b611e45565b3480156107c0575f80fd5b506107d46107cf366004613c45565b612098565b6040516102719190613c7b565b6106ae6107ef366004613ce8565b61240a565b3480156107ff575f80fd5b5061081361080e36600461351b565b6125d5565b6040519015158152602001610271565b34801561082e575f80fd5b5061084261083d36600461351b565b6126aa565b6040516102719796959493929190613d48565b348015610860575f80fd5b5061087461086f366004613600565b612855565b6040516102719796959493929190613da1565b604080516001600160a01b038416602080830191909152606682840152825180830384018152606090920190925280519101205f90816108c8826004613e17565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf86846040516020016109239291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161095791815260200190565b602060405180830381865afa158015610972573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109969190613e2a565b93505050505b92915050565b6109aa612aac565b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b5f805f805f805f805f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8b6065604051602001610a619291906001600160a01b03929092168252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600960248201526044015f60405180830381865afa158015610ab4573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610adb9190810190613e41565b6020810151606082015161010083015161012090930151919d909c5067ffffffffffffffff8084169c50604084811c82169c50608085901c82169b5060c09490941c995082169750911c63ffffffff16945092505050565b60408051606080820183525f808352602080840182905283850182905284516001600160a01b03891681830152606681870152855180820387018152930190945281519190930120829182918291829182610b8d8a612ad7565b610b98836003613e17565b604080516001600160a01b03909316602084015282015260600160408051601f1981840301815282825280516020918201209083018c905290820181905291505f9060600160408051601f19818403018152919052805160209091012090505f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166335fd631a610c32856001613e17565b60405160e083901b6001600160e01b03191681526004810191909152600260248201526044015f60405180830381865afa158015610c72573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610c999190810190613e41565b905060208101516001600160601b0381169a506001600160a01b038160601c1699506040820151905063ffffffff8116985063ffffffff8160201c16975063ffffffff8160401c169650505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf846040518263ffffffff1660e01b8152600401610d3391815260200190565b602060405180830381865afa158015610d4e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d729190613e2a565b6001600160601b038116875267ffffffffffffffff606082901c16602088015260a01c60ff16604087015250989c979b509599509397509195509392505050565b610e306040805160e081019091525f606082018181526080830182905260a0830182905260c0830191909152819081526040805160a0810182525f80825260208281018290529282018190526060820181905260808201529101908152604080516060810182525f80825260208281018290529282015291015290565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a84866069604051602001610e899291906001600160a01b03929092168252602082015260400190565b60408051601f1981840301815282825280516020918201206001600160a01b039094169083015281019190915260600160408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600360248201526044015f60405180830381865afa158015610f0c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610f339190810190613e41565b602080820151604080840151606094850151825160e0810184526001600160a01b0380861682890190815261ffff60a088811c821660808087019190915260b08a811c84168388015260c09a8b1c84168b88015293865288518083018a52858916815288831c8416818d015288851c8416818b01529988901c83168a8d015260d09790971c821696890196909652838901979097528551988901865290831688529282901c851695870195909552901c90911683820152810191909152949350505050565b604080516060810182525f808252602082018190529181018290529061101d84612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611060826003613e17565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf86846040516020016110b0929190918252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016110e491815260200190565b602060405180830381865afa1580156110ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111239190613e2a565b67ffffffffffffffff81168552604081811c63ffffffff16602087015260609190911c908501525091949350505050565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156111b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111dc9190613e2a565b9050828110156111ff5760405163409a171f60e01b815260040160405180910390fd5b801561128557604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024015f604051808303815f87803b158015611264575f80fd5b505af1158015611276573d5f803e3d5ffd5b505050506112855f8383612af9565b505050565b611292612b91565b61129b82612c48565b6112a58282612c53565b5050565b5f805f805f805f805f806112ed604080516080810182525f818301818152606083018290528252825180840190935280835260208381019190915290919082015290565b5f6112f78e612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f198184030181529190528051602090910120611337906005613e17565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8f84604051602001611387929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156113da573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526114019190810190613e41565b90505f80602083015165ffffffffffff81169f5065ffffffffffff8160301c169e506001600160a01b038160601c169d50604084015190506001600160a01b03811699506001600160601b038160a01c169c506060840151905067ffffffffffffffff81169a506001600160601b038160401c169b5065ffffffffffff8160a01c16985060ff8160d01c169750506080830151955060a0830151915060c083015190506115198282604080516080810182525f818301818152606083018290528252825180840190935280835260208084019190915281019190915280516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b9450505050509295989b509295989b9093969950565b5f611538612d27565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf8460656040516020016115b69291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016115ea91815260200190565b602060405180830381865afa158015611605573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116299190613e2a565b9392505050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf8460686040516020016115b69291906001600160a01b03929092168252602082015260400190565b5f805f805f805f806116cb604080516080810182525f818301818152606083018290528252825180840190935280835260208381019190915290919082015290565b5f6116d58c612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611718826004613e17565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8e84604051602001611768929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156117bb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526117e29190810190613e41565b90505f8060208301516001600160601b0381169e508060601c9d50604084015190506001600160601b0381169c508060601c9950606084015190506001600160601b0381169b508060601c9a506080840151905067ffffffffffffffff8160081c16985060ff8160681c1697505060a0830151915060c083015190506118d38282604080516080810182525f818301818152606083018290528252825180840190935280835260208084019190915281019190915280516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b955050505050509295985092959850929598565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166364d5d9fa8a8a8a6040518463ffffffff1660e01b815260040161193993929190613ef3565b5f604051808303815f87803b158015611950575f80fd5b505af1158015611962573d5f803e3d5ffd5b50505050611973898787878761240a565b9150915097509795505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156119cd5750825b90505f8267ffffffffffffffff1660011480156119e95750303b155b9050811580156119f7575080155b15611a155760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315611a4957845468ff00000000000000001916680100000000000000001785555b611a6c5f805473ffffffffffffffffffffffffffffffffffffffff191633179055565b611a74612d70565b8315611abf57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b604080516001600160a01b038516602080830191909152606582840152825180830384018152606092830190935282519201919091205f611b08826002613e17565b604051631e2eaeaf60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631e2eaeaf90602401602060405180830381865afa158015611b70573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b949190613e2a565b90508086101580611ba3575084155b15611bb057505050611629565b5f611bbb8783613f15565b905080861015611bc85750845b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8986604051602001611c0c91815260200190565b604051602081830303815290604052805190602001205f1c611c2e9190613e17565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa158015611c6e573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611c959190810190613e41565b90508167ffffffffffffffff811115611cb057611cb0613649565b604051908082528060200260200182016040528015611cd9578160200160208202803683370190505b50955060208083600101025b80821015611d00578183015182890152602082019150611ce5565b505050505050509392505050565b60605f8267ffffffffffffffff811115611d2a57611d2a613649565b604051908082528060200260200182016040528015611d5d57816020015b6060815260200190600190039081611d485790505b5090505f5b83811015611e3d575f8030878785818110611d7f57611d7f613f28565b9050602002810190611d919190613f3c565b604051611d9f929190613f7f565b5f60405180830381855af49150503d805f8114611dd7576040519150601f19603f3d011682016040523d82523d5f602084013e611ddc565b606091505b50915091508115611e0a5780848481518110611dfa57611dfa613f28565b6020026020010181905250611e33565b805115611e1a5780518082602001fd5b6040516302cf089f60e51b815260040160405180910390fd5b5050600101611d62565b509392505050565b5f80611e5b69d3c21bcecceda100000086613f8e565b90505f611e678861155d565b9050611e93887f0000000000000000000000000000000000000000000000000000000000000000612d78565b611ebe817f000000000000000000000000000000000000000000000000000000000000000084612e52565b611efc8833308a8a808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250612f4992505050565b60405162e592a960e61b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633964aa4090611f4d908b908b908b903390600401613fa5565b5f604051808303815f87803b158015611f64575f80fd5b505af1158015611f76573d5f803e3d5ffd5b50506040516323b872dd60e01b8152336004820152306024820152604481018590526001600160a01b03841692506323b872dd91506064016020604051808303815f875af1158015611fca573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fee9190613fdc565b5060405163c04b8d5960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c04b8d599061203b908790600401614048565b6020604051808303815f875af1158015612057573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061207b9190613e2a565b9250841561208d5761208d8333611154565b505095945050505050565b60605f6120a486612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f6120e7826005613e17565b60408051602081018990529081018290529091505f9060600160408051601f198184030181529190528051602090910120612123906003613e17565b604051631e2eaeaf60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631e2eaeaf90602401602060405180830381865afa15801561218b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121af9190613e2a565b905080871015806121be575085155b156121cc5750505050612402565b5f6121d78883613f15565b9050808710156121e45750855b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8a8660405160200161222891815260200190565b604051602081830303815290604052805190602001205f1c61224a9190613e17565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa15801561228a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526122b19190810190613e41565b90508167ffffffffffffffff8111156122cc576122cc613649565b60405190808252806020026020018201604052801561231557816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816122ea5790505b5096505f5b828110156123fa575f6020600183010283015190506001600160a01b03811689838151811061234b5761234b613f28565b60200260200101515f01906001600160a01b031690816001600160a01b03168152505065ffffffffffff60a082901c1689838151811061238d5761238d613f28565b60200260200101516020019065ffffffffffff16908165ffffffffffff168152505065ffffffffffff60d082901c168983815181106123ce576123ce613f28565b602090810291909101015165ffffffffffff909116604090910152506123f38161405a565b905061231a565b505050505050505b949350505050565b5f808061242169d3c21bcecceda100000088613f8e565b90505f61242d8961155d565b905061245a817f000000000000000000000000000000000000000000000000000000000000000084612e52565b612465338787612f8a565b93505f82866060015111612479575f612489565b8286606001516124899190613f15565b90508015612515576040516346d5785160e11b81523060048201526001600160a01b038381166024830152604482018390527f00000000000000000000000000000000000000000000000000000000000000001690638daaf0a2906064015f604051808303815f87803b1580156124fe575f80fd5b505af1158015612510573d5f803e3d5ffd5b505050505b60405163fdbed69960e01b81526001600160a01b038b81166004830152602482018b9052604482018a90523360648301527f0000000000000000000000000000000000000000000000000000000000000000169063fdbed699906084016020604051808303815f875af115801561258e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125b29190613e2a565b93508015806125c057508084145b6125c8575f80fd5b5050509550959350505050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf84606760405160200161262e9291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161266291815260200190565b602060405180830381865afa15801561267d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126a19190613e2a565b15159392505050565b5f805f60605f805f808860666040516020016126db9291906001600160a01b03929092168252602082015260400190565b60408051601f19818403018152908290528051602090910120631afeb18d60e11b8252600482018190526006602483015291505f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906335fd631a906044015f60405180830381865afa15801561275e573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526127859190810190613e41565b602080820151604083015160608085015160c08601516001600160601b0385169f509390911c9c50985063ffffffff82169750911c61ffff16945090915060086040519080825280602002602001820160405280156127ee578160200160208202803683370190505b50965060f081901c60ff1697505f5b600881101561284657612811816018613f8e565b82901c62ffffff1688828151811061282b5761282b613f28565b602090810291909101015261283f8161405a565b90506127fd565b50505050919395979092949650565b5f805f805f80612895604080516080810182525f818301818152606083018290528252825180840190935280835260208381019190915290919082015290565b5f61289f8a612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f6128e2826006613e17565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8c84604051602001612932929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600560248201526044015f60405180830381865afa158015612985573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129ac9190810190613e41565b90505f8060208301516001600160601b0381169c506001600160a01b038160601c169b50604084015190506001600160601b0381169a506001600160a01b038160601c169950606084015190506001600160a01b038116985067ffffffffffffffff8160a01c169750506080830151915060a08301519050612a998282604080516080810182525f818301818152606083018290528252825180840190935280835260208084019190915281019190915280516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b9550505050505092959891949750929550565b5f546001600160a01b03163314612ad5576040516282b42960e81b815260040160405180910390fd5b565b5f80612ae283611630565b90506001600160a01b03811661099c575090919050565b5f6001600160a01b038416612b35575f805f8085875af1905080612b3057604051633d2cec6f60e21b815260040160405180910390fd5b612b8b565b60405163a9059cbb60e01b5f52836004528260245260205f60445f80895af13d15601f3d1160015f511416171691505f606052806040525080612b8b57604051633c9fd93960e21b815260040160405180910390fd5b50505050565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480612c2a57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612c1e7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15612ad55760405163703e46dd60e11b815260040160405180910390fd5b612c50612aac565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612cad575060408051601f3d908101601f19168201909252612caa91810190613e2a565b60015b612cda57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612d1d57604051632a87526960e21b815260048101829052602401612cd1565b61128583836131e2565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614612ad55760405163703e46dd60e11b815260040160405180910390fd5b612ad5613237565b60405163e985e9c560e01b81523060048201526001600160a01b0382811660248301525f919084169063e985e9c590604401602060405180830381865afa158015612dc5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612de99190613fdc565b9050806112855760405163a22cb46560e01b81526001600160a01b0383811660048301526001602483015284169063a22cb465906044015f604051808303815f87803b158015612e37575f80fd5b505af1158015612e49573d5f803e3d5ffd5b50505050505050565b805f03612e5e57505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015612eab573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ecf9190613e2a565b905081811015612b8b5760405163095ea7b360e01b81526001600160a01b0384811660048301525f19602483015285169063095ea7b3906044016020604051808303815f875af1158015612f25573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abf9190613fdc565b80515f5b81811015612f8257612f7a868686868581518110612f6d57612f6d613f28565b6020026020010151613285565b600101612f4d565b505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316148015612fd0575081608001514710155b156130ef576080820151604051631e51809360e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163f28c049891613026908690600401614048565b60206040518083038185885af1158015613042573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906130679190613e2a565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166312210e8a6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156130c1575f80fd5b505af11580156130d3573d5f803e3d5ffd5b505050505f4711156130ea576130ea5f8547612af9565b611629565b61311e837f00000000000000000000000000000000000000000000000000000000000000008460800151612e52565b61312e83853085608001516132e0565b604051631e51809360e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f28c04989061317a908590600401614048565b6020604051808303815f875af1158015613196573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ba9190613e2a565b905080826080015111156116295761162983858385608001516131dd9190613f15565b612af9565b6131eb8261333b565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561322f5761128582826133be565b6112a5613430565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16612ad557604051631afcd79f60e31b815260040160405180910390fd5b5f604051632142170760e11b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f606052806040525080611abf57604051636ff8a60f60e11b815260040160405180910390fd5b5f6040516323b872dd60e01b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f606052806040525080611abf57604051633c9fd93960e21b815260040160405180910390fd5b806001600160a01b03163b5f0361337057604051634c9c8ce360e01b81526001600160a01b0382166004820152602401612cd1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516133da9190614072565b5f60405180830381855af49150503d805f8114613412576040519150601f19603f3d011682016040523d82523d5f602084013e613417565b606091505b509150915061342785838361344f565b95945050505050565b3415612ad55760405163b398979f60e01b815260040160405180910390fd5b60608261345f576130ea826134a6565b815115801561347657506001600160a01b0384163b155b1561349f57604051639996b31560e01b81526001600160a01b0385166004820152602401612cd1565b5080611629565b8051156134b65780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146134e5575f80fd5b919050565b5f80604083850312156134fb575f80fd5b613504836134cf565b9150613512602084016134cf565b90509250929050565b5f6020828403121561352b575f80fd5b611629826134cf565b5f805f805f60808688031215613548575f80fd5b613551866134cf565b945061355f602087016134cf565b935060408601359250606086013567ffffffffffffffff80821115613582575f80fd5b818801915088601f830112613595575f80fd5b8135818111156135a3575f80fd5b8960208285010111156135b4575f80fd5b9699959850939650602001949392505050565b5f805f606084860312156135d9575f80fd5b6135e2846134cf565b92506135f0602085016134cf565b9150604084013590509250925092565b5f8060408385031215613611575f80fd5b61361a836134cf565b946020939093013593505050565b5f8060408385031215613639575f80fd5b82359150613512602084016134cf565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561368657613686613649565b604052919050565b5f67ffffffffffffffff8211156136a7576136a7613649565b50601f01601f191660200190565b5f82601f8301126136c4575f80fd5b81356136d76136d28261368e565b61365d565b8181528460208386010111156136eb575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613718575f80fd5b613721836134cf565b9150602083013567ffffffffffffffff81111561373c575f80fd5b613748858286016136b5565b9150509250929050565b61377482825180516001600160a01b0316825260209081015161ffff16910152565b60209081015180516001600160a01b03166040840152015161ffff16606090910152565b65ffffffffffff8c811682528b811660208301526001600160a01b038b811660408401526001600160601b038b811660608501528a16608084015267ffffffffffffffff891660a0840152871660c0830152851660e082015283151561010082015261012081018390526101c08101613815610140830184613752565b9c9b505050505050505050505050565b6001600160601b038a1681526001600160a01b0389811660208301526fffffffffffffffffffffffffffffffff8981166040840152881660608301528681166080830152851660a082015267ffffffffffffffff841660c08201526101808101600384106138a157634e487b7160e01b5f52602160045260245ffd5b8360e08301526138b5610100830184613752565b9a9950505050505050505050565b5f8083601f8401126138d3575f80fd5b50813567ffffffffffffffff8111156138ea575f80fd5b6020830191508360208260051b8501011115613904575f80fd5b9250929050565b5f60a0828403121561391b575f80fd5b60405160a0810167ffffffffffffffff828210818311171561393f5761393f613649565b816040528293508435915080821115613956575f80fd5b50613963858286016136b5565b825250613972602084016134cf565b60208201526040830135604082015260608301356060820152608083013560808201525092915050565b5f805f805f805f60c0888a0312156139b2575f80fd5b6139bb886134cf565b9650602088013567ffffffffffffffff808211156139d7575f80fd5b6139e38b838c016138c3565b909850965060408a0135955060608a01359450869150613a0560808b016134cf565b935060a08a0135915080821115613a1a575f80fd5b50613a278a828b0161390b565b91505092959891949750929550565b5f805f60608486031215613a48575f80fd5b613a51846134cf565b95602085013595506040909401359392505050565b5f8151808452602080850194508084015f5b83811015613a9457815187529582019590820190600101613a78565b509495945050505050565b602081525f6116296020830184613a66565b5f8060208385031215613ac2575f80fd5b823567ffffffffffffffff811115613ad8575f80fd5b613ae4858286016138c3565b90969095509350505050565b5f5b83811015613b0a578181015183820152602001613af2565b50505f910152565b5f8151808452613b29816020860160208601613af0565b601f01601f19169290920160200192915050565b5f602080830181845280855180835260408601915060408160051b87010192508387015f5b82811015613b9057603f19888603018452613b7e858351613b12565b94509285019290850190600101613b62565b5092979650505050505050565b602081525f6116296020830184613b12565b8015158114612c50575f80fd5b5f805f805f60808688031215613bd0575f80fd5b613bd9866134cf565b9450602086013567ffffffffffffffff80821115613bf5575f80fd5b613c0189838a016138c3565b909650945060408801359150613c1682613baf565b90925060608701359080821115613c2b575f80fd5b50613c388882890161390b565b9150509295509295909350565b5f805f8060808587031215613c58575f80fd5b613c61856134cf565b966020860135965060408601359560600135945092505050565b602080825282518282018190525f919060409081850190868401855b82811015613cdb57815180516001600160a01b031685528681015165ffffffffffff9081168887015290860151168585015260609093019290850190600101613c97565b5091979650505050505050565b5f805f805f60a08688031215613cfc575f80fd5b613d05866134cf565b94506020860135935060408601359250613d21606087016134cf565b9150608086013567ffffffffffffffff811115613d3c575f80fd5b613c388882890161390b565b8781526001600160a01b038716602082015260ff8616604082015260e060608201525f613d7860e0830187613a66565b60808301959095525063ffffffff9290921660a083015261ffff1660c090910152949350505050565b6001600160601b0388811682526001600160a01b038881166020840152908716604083015285811660608301528416608082015267ffffffffffffffff831660a08201526101408101613df760c0830184613752565b98975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561099c5761099c613e03565b5f60208284031215613e3a575f80fd5b5051919050565b5f60208284031215613e51575f80fd5b815167ffffffffffffffff811115613e67575f80fd5b8201601f81018413613e77575f80fd5b8051613e856136d28261368e565b818152856020838501011115613e99575f80fd5b613427826020830160208601613af0565b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613eda575f80fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0384168152604060208201525f613427604083018486613eaa565b8181038181111561099c5761099c613e03565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e19843603018112613f51575f80fd5b83018035915067ffffffffffffffff821115613f6b575f80fd5b602001915036819003821315613904575f80fd5b818382375f9101908152919050565b808202811582820484141761099c5761099c613e03565b5f6001600160a01b03808716835260606020840152613fc8606084018688613eaa565b915080841660408401525095945050505050565b5f60208284031215613fec575f80fd5b815161162981613baf565b5f815160a0845261400b60a0850182613b12565b90506001600160a01b0360208401511660208501526040830151604085015260608301516060850152608083015160808501528091505092915050565b602081525f6116296020830184613ff7565b5f6001820161406b5761406b613e03565b5060010190565b5f8251614083818460208701613af0565b919091019291505056fea164736f6c6343000814000a0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Deployed Bytecode
0x6080604052600436106101bd575f3560e01c8063725d33b0116100f2578063ac9650d811610092578063deefbf8711610062578063deefbf87146107e1578063e2c6e438146107f4578063ea5eda3214610823578063ef2d242714610855575f80fd5b8063ac9650d814610721578063ad3cb1cc1461074d578063c660093d146107a2578063c999b80e146107b5575f80fd5b806376c90757116100cd57806376c907571461069b5780638129fc1c146106c3578063824d3575146106d75780638da5cb5b14610703575f80fd5b8063725d33b014610615578063735de9f714610634578063762a66a214610667575f80fd5b80633c777f411161015d5780634f1ef286116101385780634f1ef286146105995780634f67caa7146105ac57806352d1902d146105e25780635818ea1c146105f6575f80fd5b80633c777f411461050857806349404b7c146105535780634aa4a4fc14610566575f80fd5b80631f0c602d116101985780631f0c602d146102dd57806321dfa77b1461035957806329e81d71146103e3578063316d1a21146104ae575f80fd5b80631049334f1461024857806313af40351461027a578063150b7a0214610299575f80fd5b3661024457336001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156416148015906102245750336001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21614155b1561024257604051639f5c13f160e01b815260040160405180910390fd5b005b5f80fd5b348015610253575f80fd5b506102676102623660046134ea565b610887565b6040519081526020015b60405180910390f35b348015610285575f80fd5b5061024261029436600461351b565b6109a2565b3480156102a4575f80fd5b506102c46102b3366004613534565b630a85bd0160e11b95945050505050565b6040516001600160e01b03199091168152602001610271565b3480156102e8575f80fd5b506102fc6102f736600461351b565b610a01565b604080516001600160a01b039099168952602089019790975267ffffffffffffffff9586169688019690965292841660608701529083166080860152821660a08501521660c083015263ffffffff1660e082015261010001610271565b348015610364575f80fd5b506103786103733660046135c7565b610b33565b604080519687526001600160a01b0390951660208088019190915263ffffffff9485168787015292841660608701529216608085015281516001600160601b031660a085015281015167ffffffffffffffff1660c0840152015160ff1660e082015261010001610271565b3480156103ee575f80fd5b506104026103fd3660046134ea565b610db3565b6040516102719190815180516001600160a01b03908116835260208083015161ffff90811682860152604080850151821681870152606094850151821685870152828701518051851660808089019190915281850151841660a089015281830151841660c089015295810151831660e088015294909401518116610100860152948301518051909216610120850152810151841661014084015201519091166101608201526101800190565b3480156104b9575f80fd5b506104cd6104c8366004613600565b610ff8565b60408051825167ffffffffffffffff16815260208084015163ffffffff1690820152918101516001600160a01b031690820152606001610271565b348015610513575f80fd5b5061053b7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da281565b6040516001600160a01b039091168152602001610271565b610242610561366004613628565b611154565b348015610571575f80fd5b5061053b7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6102426105a7366004613707565b61128a565b3480156105b7575f80fd5b506105cb6105c6366004613600565b6112a9565b6040516102719b9a99989796959493929190613798565b3480156105ed575f80fd5b5061026761152f565b348015610601575f80fd5b5061053b61061036600461351b565b61155d565b348015610620575f80fd5b5061053b61062f36600461351b565b611630565b34801561063f575f80fd5b5061053b7f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b348015610672575f80fd5b50610686610681366004613600565b611689565b60405161027199989796959493929190613825565b6106ae6106a936600461399c565b6118e7565b60408051928352602083019190915201610271565b3480156106ce575f80fd5b50610242611983565b3480156106e2575f80fd5b506106f66106f1366004613a36565b611ac6565b6040516102719190613a9f565b34801561070e575f80fd5b505f5461053b906001600160a01b031681565b34801561072c575f80fd5b5061074061073b366004613ab1565b611d0e565b6040516102719190613b3d565b348015610758575f80fd5b506107956040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516102719190613b9d565b6102676107b0366004613bbc565b611e45565b3480156107c0575f80fd5b506107d46107cf366004613c45565b612098565b6040516102719190613c7b565b6106ae6107ef366004613ce8565b61240a565b3480156107ff575f80fd5b5061081361080e36600461351b565b6125d5565b6040519015158152602001610271565b34801561082e575f80fd5b5061084261083d36600461351b565b6126aa565b6040516102719796959493929190613d48565b348015610860575f80fd5b5061087461086f366004613600565b612855565b6040516102719796959493929190613da1565b604080516001600160a01b038416602080830191909152606682840152825180830384018152606090920190925280519101205f90816108c8826004613e17565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf86846040516020016109239291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161095791815260200190565b602060405180830381865afa158015610972573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109969190613e2a565b93505050505b92915050565b6109aa612aac565b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b5f805f805f805f805f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8b6065604051602001610a619291906001600160a01b03929092168252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600960248201526044015f60405180830381865afa158015610ab4573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610adb9190810190613e41565b6020810151606082015161010083015161012090930151919d909c5067ffffffffffffffff8084169c50604084811c82169c50608085901c82169b5060c09490941c995082169750911c63ffffffff16945092505050565b60408051606080820183525f808352602080840182905283850182905284516001600160a01b03891681830152606681870152855180820387018152930190945281519190930120829182918291829182610b8d8a612ad7565b610b98836003613e17565b604080516001600160a01b03909316602084015282015260600160408051601f1981840301815282825280516020918201209083018c905290820181905291505f9060600160408051601f19818403018152919052805160209091012090505f6001600160a01b037f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2166335fd631a610c32856001613e17565b60405160e083901b6001600160e01b03191681526004810191909152600260248201526044015f60405180830381865afa158015610c72573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610c999190810190613e41565b905060208101516001600160601b0381169a506001600160a01b038160601c1699506040820151905063ffffffff8116985063ffffffff8160201c16975063ffffffff8160401c169650505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf846040518263ffffffff1660e01b8152600401610d3391815260200190565b602060405180830381865afa158015610d4e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d729190613e2a565b6001600160601b038116875267ffffffffffffffff606082901c16602088015260a01c60ff16604087015250989c979b509599509397509195509392505050565b610e306040805160e081019091525f606082018181526080830182905260a0830182905260c0830191909152819081526040805160a0810182525f80825260208281018290529282018190526060820181905260808201529101908152604080516060810182525f80825260208281018290529282015291015290565b5f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a84866069604051602001610e899291906001600160a01b03929092168252602082015260400190565b60408051601f1981840301815282825280516020918201206001600160a01b039094169083015281019190915260600160408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600360248201526044015f60405180830381865afa158015610f0c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610f339190810190613e41565b602080820151604080840151606094850151825160e0810184526001600160a01b0380861682890190815261ffff60a088811c821660808087019190915260b08a811c84168388015260c09a8b1c84168b88015293865288518083018a52858916815288831c8416818d015288851c8416818b01529988901c83168a8d015260d09790971c821696890196909652838901979097528551988901865290831688529282901c851695870195909552901c90911683820152810191909152949350505050565b604080516060810182525f808252602082018190529181018290529061101d84612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611060826003613e17565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf86846040516020016110b0929190918252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016110e491815260200190565b602060405180830381865afa1580156110ff573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111239190613e2a565b67ffffffffffffffff81168552604081811c63ffffffff16602087015260609190911c908501525091949350505050565b6040516370a0823160e01b81523060048201525f907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316906370a0823190602401602060405180830381865afa1580156111b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111dc9190613e2a565b9050828110156111ff5760405163409a171f60e01b815260040160405180910390fd5b801561128557604051632e1a7d4d60e01b8152600481018290527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031690632e1a7d4d906024015f604051808303815f87803b158015611264575f80fd5b505af1158015611276573d5f803e3d5ffd5b505050506112855f8383612af9565b505050565b611292612b91565b61129b82612c48565b6112a58282612c53565b5050565b5f805f805f805f805f806112ed604080516080810182525f818301818152606083018290528252825180840190935280835260208381019190915290919082015290565b5f6112f78e612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f198184030181529190528051602090910120611337906005613e17565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8f84604051602001611387929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156113da573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526114019190810190613e41565b90505f80602083015165ffffffffffff81169f5065ffffffffffff8160301c169e506001600160a01b038160601c169d50604084015190506001600160a01b03811699506001600160601b038160a01c169c506060840151905067ffffffffffffffff81169a506001600160601b038160401c169b5065ffffffffffff8160a01c16985060ff8160d01c169750506080830151955060a0830151915060c083015190506115198282604080516080810182525f818301818152606083018290528252825180840190935280835260208084019190915281019190915280516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b9450505050509295989b509295989b9093969950565b5f611538612d27565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf8460656040516020016115b69291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016115ea91815260200190565b602060405180830381865afa158015611605573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116299190613e2a565b9392505050565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf8460686040516020016115b69291906001600160a01b03929092168252602082015260400190565b5f805f805f805f806116cb604080516080810182525f818301818152606083018290528252825180840190935280835260208381019190915290919082015290565b5f6116d58c612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611718826004613e17565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8e84604051602001611768929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156117bb573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526117e29190810190613e41565b90505f8060208301516001600160601b0381169e508060601c9d50604084015190506001600160601b0381169c508060601c9950606084015190506001600160601b0381169b508060601c9a506080840151905067ffffffffffffffff8160081c16985060ff8160681c1697505060a0830151915060c083015190506118d38282604080516080810182525f818301818152606083018290528252825180840190935280835260208084019190915281019190915280516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b955050505050509295985092959850929598565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166364d5d9fa8a8a8a6040518463ffffffff1660e01b815260040161193993929190613ef3565b5f604051808303815f87803b158015611950575f80fd5b505af1158015611962573d5f803e3d5ffd5b50505050611973898787878761240a565b9150915097509795505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f811580156119cd5750825b90505f8267ffffffffffffffff1660011480156119e95750303b155b9050811580156119f7575080155b15611a155760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315611a4957845468ff00000000000000001916680100000000000000001785555b611a6c5f805473ffffffffffffffffffffffffffffffffffffffff191633179055565b611a74612d70565b8315611abf57845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b604080516001600160a01b038516602080830191909152606582840152825180830384018152606092830190935282519201919091205f611b08826002613e17565b604051631e2eaeaf60e01b8152600481018290529091505f907f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b031690631e2eaeaf90602401602060405180830381865afa158015611b70573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b949190613e2a565b90508086101580611ba3575084155b15611bb057505050611629565b5f611bbb8783613f15565b905080861015611bc85750845b5f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8986604051602001611c0c91815260200190565b604051602081830303815290604052805190602001205f1c611c2e9190613e17565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa158015611c6e573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611c959190810190613e41565b90508167ffffffffffffffff811115611cb057611cb0613649565b604051908082528060200260200182016040528015611cd9578160200160208202803683370190505b50955060208083600101025b80821015611d00578183015182890152602082019150611ce5565b505050505050509392505050565b60605f8267ffffffffffffffff811115611d2a57611d2a613649565b604051908082528060200260200182016040528015611d5d57816020015b6060815260200190600190039081611d485790505b5090505f5b83811015611e3d575f8030878785818110611d7f57611d7f613f28565b9050602002810190611d919190613f3c565b604051611d9f929190613f7f565b5f60405180830381855af49150503d805f8114611dd7576040519150601f19603f3d011682016040523d82523d5f602084013e611ddc565b606091505b50915091508115611e0a5780848481518110611dfa57611dfa613f28565b6020026020010181905250611e33565b805115611e1a5780518082602001fd5b6040516302cf089f60e51b815260040160405180910390fd5b5050600101611d62565b509392505050565b5f80611e5b69d3c21bcecceda100000086613f8e565b90505f611e678861155d565b9050611e93887f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2612d78565b611ebe817f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156484612e52565b611efc8833308a8a808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250612f4992505050565b60405162e592a960e61b81526001600160a01b037f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da21690633964aa4090611f4d908b908b908b903390600401613fa5565b5f604051808303815f87803b158015611f64575f80fd5b505af1158015611f76573d5f803e3d5ffd5b50506040516323b872dd60e01b8152336004820152306024820152604481018590526001600160a01b03841692506323b872dd91506064016020604051808303815f875af1158015611fca573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fee9190613fdc565b5060405163c04b8d5960e01b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169063c04b8d599061203b908790600401614048565b6020604051808303815f875af1158015612057573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061207b9190613e2a565b9250841561208d5761208d8333611154565b505095945050505050565b60605f6120a486612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f6120e7826005613e17565b60408051602081018990529081018290529091505f9060600160408051601f198184030181529190528051602090910120612123906003613e17565b604051631e2eaeaf60e01b8152600481018290529091505f907f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b031690631e2eaeaf90602401602060405180830381865afa15801561218b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121af9190613e2a565b905080871015806121be575085155b156121cc5750505050612402565b5f6121d78883613f15565b9050808710156121e45750855b5f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8a8660405160200161222891815260200190565b604051602081830303815290604052805190602001205f1c61224a9190613e17565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa15801561228a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526122b19190810190613e41565b90508167ffffffffffffffff8111156122cc576122cc613649565b60405190808252806020026020018201604052801561231557816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816122ea5790505b5096505f5b828110156123fa575f6020600183010283015190506001600160a01b03811689838151811061234b5761234b613f28565b60200260200101515f01906001600160a01b031690816001600160a01b03168152505065ffffffffffff60a082901c1689838151811061238d5761238d613f28565b60200260200101516020019065ffffffffffff16908165ffffffffffff168152505065ffffffffffff60d082901c168983815181106123ce576123ce613f28565b602090810291909101015165ffffffffffff909116604090910152506123f38161405a565b905061231a565b505050505050505b949350505050565b5f808061242169d3c21bcecceda100000088613f8e565b90505f61242d8961155d565b905061245a817f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da284612e52565b612465338787612f8a565b93505f82866060015111612479575f612489565b8286606001516124899190613f15565b90508015612515576040516346d5785160e11b81523060048201526001600160a01b038381166024830152604482018390527f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da21690638daaf0a2906064015f604051808303815f87803b1580156124fe575f80fd5b505af1158015612510573d5f803e3d5ffd5b505050505b60405163fdbed69960e01b81526001600160a01b038b81166004830152602482018b9052604482018a90523360648301527f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2169063fdbed699906084016020604051808303815f875af115801561258e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125b29190613e2a565b93508015806125c057508084145b6125c8575f80fd5b5050509550959350505050565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf84606760405160200161262e9291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161266291815260200190565b602060405180830381865afa15801561267d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126a19190613e2a565b15159392505050565b5f805f60605f805f808860666040516020016126db9291906001600160a01b03929092168252602082015260400190565b60408051601f19818403018152908290528051602090910120631afeb18d60e11b8252600482018190526006602483015291505f906001600160a01b037f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da216906335fd631a906044015f60405180830381865afa15801561275e573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526127859190810190613e41565b602080820151604083015160608085015160c08601516001600160601b0385169f509390911c9c50985063ffffffff82169750911c61ffff16945090915060086040519080825280602002602001820160405280156127ee578160200160208202803683370190505b50965060f081901c60ff1697505f5b600881101561284657612811816018613f8e565b82901c62ffffff1688828151811061282b5761282b613f28565b602090810291909101015261283f8161405a565b90506127fd565b50505050919395979092949650565b5f805f805f80612895604080516080810182525f818301818152606083018290528252825180840190935280835260208381019190915290919082015290565b5f61289f8a612ad7565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f6128e2826006613e17565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8c84604051602001612932929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600560248201526044015f60405180830381865afa158015612985573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129ac9190810190613e41565b90505f8060208301516001600160601b0381169c506001600160a01b038160601c169b50604084015190506001600160601b0381169a506001600160a01b038160601c169950606084015190506001600160a01b038116985067ffffffffffffffff8160a01c169750506080830151915060a08301519050612a998282604080516080810182525f818301818152606083018290528252825180840190935280835260208084019190915281019190915280516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b9550505050505092959891949750929550565b5f546001600160a01b03163314612ad5576040516282b42960e81b815260040160405180910390fd5b565b5f80612ae283611630565b90506001600160a01b03811661099c575090919050565b5f6001600160a01b038416612b35575f805f8085875af1905080612b3057604051633d2cec6f60e21b815260040160405180910390fd5b612b8b565b60405163a9059cbb60e01b5f52836004528260245260205f60445f80895af13d15601f3d1160015f511416171691505f606052806040525080612b8b57604051633c9fd93960e21b815260040160405180910390fd5b50505050565b306001600160a01b037f0000000000000000000000002e43130be449511dc32775f1e07dbf0eb1803515161480612c2a57507f0000000000000000000000002e43130be449511dc32775f1e07dbf0eb18035156001600160a01b0316612c1e7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15612ad55760405163703e46dd60e11b815260040160405180910390fd5b612c50612aac565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612cad575060408051601f3d908101601f19168201909252612caa91810190613e2a565b60015b612cda57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612d1d57604051632a87526960e21b815260048101829052602401612cd1565b61128583836131e2565b306001600160a01b037f0000000000000000000000002e43130be449511dc32775f1e07dbf0eb18035151614612ad55760405163703e46dd60e11b815260040160405180910390fd5b612ad5613237565b60405163e985e9c560e01b81523060048201526001600160a01b0382811660248301525f919084169063e985e9c590604401602060405180830381865afa158015612dc5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612de99190613fdc565b9050806112855760405163a22cb46560e01b81526001600160a01b0383811660048301526001602483015284169063a22cb465906044015f604051808303815f87803b158015612e37575f80fd5b505af1158015612e49573d5f803e3d5ffd5b50505050505050565b805f03612e5e57505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015612eab573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ecf9190613e2a565b905081811015612b8b5760405163095ea7b360e01b81526001600160a01b0384811660048301525f19602483015285169063095ea7b3906044016020604051808303815f875af1158015612f25573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abf9190613fdc565b80515f5b81811015612f8257612f7a868686868581518110612f6d57612f6d613f28565b6020026020010151613285565b600101612f4d565b505050505050565b5f7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316836001600160a01b0316148015612fd0575081608001514710155b156130ef576080820151604051631e51809360e31b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169163f28c049891613026908690600401614048565b60206040518083038185885af1158015613042573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906130679190613e2a565b90507f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b03166312210e8a6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156130c1575f80fd5b505af11580156130d3573d5f803e3d5ffd5b505050505f4711156130ea576130ea5f8547612af9565b611629565b61311e837f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615648460800151612e52565b61312e83853085608001516132e0565b604051631e51809360e31b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169063f28c04989061317a908590600401614048565b6020604051808303815f875af1158015613196573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ba9190613e2a565b905080826080015111156116295761162983858385608001516131dd9190613f15565b612af9565b6131eb8261333b565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561322f5761128582826133be565b6112a5613430565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16612ad557604051631afcd79f60e31b815260040160405180910390fd5b5f604051632142170760e11b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f606052806040525080611abf57604051636ff8a60f60e11b815260040160405180910390fd5b5f6040516323b872dd60e01b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f606052806040525080611abf57604051633c9fd93960e21b815260040160405180910390fd5b806001600160a01b03163b5f0361337057604051634c9c8ce360e01b81526001600160a01b0382166004820152602401612cd1565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516133da9190614072565b5f60405180830381855af49150503d805f8114613412576040519150601f19603f3d011682016040523d82523d5f602084013e613417565b606091505b509150915061342785838361344f565b95945050505050565b3415612ad55760405163b398979f60e01b815260040160405180910390fd5b60608261345f576130ea826134a6565b815115801561347657506001600160a01b0384163b155b1561349f57604051639996b31560e01b81526001600160a01b0385166004820152602401612cd1565b5080611629565b8051156134b65780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80356001600160a01b03811681146134e5575f80fd5b919050565b5f80604083850312156134fb575f80fd5b613504836134cf565b9150613512602084016134cf565b90509250929050565b5f6020828403121561352b575f80fd5b611629826134cf565b5f805f805f60808688031215613548575f80fd5b613551866134cf565b945061355f602087016134cf565b935060408601359250606086013567ffffffffffffffff80821115613582575f80fd5b818801915088601f830112613595575f80fd5b8135818111156135a3575f80fd5b8960208285010111156135b4575f80fd5b9699959850939650602001949392505050565b5f805f606084860312156135d9575f80fd5b6135e2846134cf565b92506135f0602085016134cf565b9150604084013590509250925092565b5f8060408385031215613611575f80fd5b61361a836134cf565b946020939093013593505050565b5f8060408385031215613639575f80fd5b82359150613512602084016134cf565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561368657613686613649565b604052919050565b5f67ffffffffffffffff8211156136a7576136a7613649565b50601f01601f191660200190565b5f82601f8301126136c4575f80fd5b81356136d76136d28261368e565b61365d565b8181528460208386010111156136eb575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613718575f80fd5b613721836134cf565b9150602083013567ffffffffffffffff81111561373c575f80fd5b613748858286016136b5565b9150509250929050565b61377482825180516001600160a01b0316825260209081015161ffff16910152565b60209081015180516001600160a01b03166040840152015161ffff16606090910152565b65ffffffffffff8c811682528b811660208301526001600160a01b038b811660408401526001600160601b038b811660608501528a16608084015267ffffffffffffffff891660a0840152871660c0830152851660e082015283151561010082015261012081018390526101c08101613815610140830184613752565b9c9b505050505050505050505050565b6001600160601b038a1681526001600160a01b0389811660208301526fffffffffffffffffffffffffffffffff8981166040840152881660608301528681166080830152851660a082015267ffffffffffffffff841660c08201526101808101600384106138a157634e487b7160e01b5f52602160045260245ffd5b8360e08301526138b5610100830184613752565b9a9950505050505050505050565b5f8083601f8401126138d3575f80fd5b50813567ffffffffffffffff8111156138ea575f80fd5b6020830191508360208260051b8501011115613904575f80fd5b9250929050565b5f60a0828403121561391b575f80fd5b60405160a0810167ffffffffffffffff828210818311171561393f5761393f613649565b816040528293508435915080821115613956575f80fd5b50613963858286016136b5565b825250613972602084016134cf565b60208201526040830135604082015260608301356060820152608083013560808201525092915050565b5f805f805f805f60c0888a0312156139b2575f80fd5b6139bb886134cf565b9650602088013567ffffffffffffffff808211156139d7575f80fd5b6139e38b838c016138c3565b909850965060408a0135955060608a01359450869150613a0560808b016134cf565b935060a08a0135915080821115613a1a575f80fd5b50613a278a828b0161390b565b91505092959891949750929550565b5f805f60608486031215613a48575f80fd5b613a51846134cf565b95602085013595506040909401359392505050565b5f8151808452602080850194508084015f5b83811015613a9457815187529582019590820190600101613a78565b509495945050505050565b602081525f6116296020830184613a66565b5f8060208385031215613ac2575f80fd5b823567ffffffffffffffff811115613ad8575f80fd5b613ae4858286016138c3565b90969095509350505050565b5f5b83811015613b0a578181015183820152602001613af2565b50505f910152565b5f8151808452613b29816020860160208601613af0565b601f01601f19169290920160200192915050565b5f602080830181845280855180835260408601915060408160051b87010192508387015f5b82811015613b9057603f19888603018452613b7e858351613b12565b94509285019290850190600101613b62565b5092979650505050505050565b602081525f6116296020830184613b12565b8015158114612c50575f80fd5b5f805f805f60808688031215613bd0575f80fd5b613bd9866134cf565b9450602086013567ffffffffffffffff80821115613bf5575f80fd5b613c0189838a016138c3565b909650945060408801359150613c1682613baf565b90925060608701359080821115613c2b575f80fd5b50613c388882890161390b565b9150509295509295909350565b5f805f8060808587031215613c58575f80fd5b613c61856134cf565b966020860135965060408601359560600135945092505050565b602080825282518282018190525f919060409081850190868401855b82811015613cdb57815180516001600160a01b031685528681015165ffffffffffff9081168887015290860151168585015260609093019290850190600101613c97565b5091979650505050505050565b5f805f805f60a08688031215613cfc575f80fd5b613d05866134cf565b94506020860135935060408601359250613d21606087016134cf565b9150608086013567ffffffffffffffff811115613d3c575f80fd5b613c388882890161390b565b8781526001600160a01b038716602082015260ff8616604082015260e060608201525f613d7860e0830187613a66565b60808301959095525063ffffffff9290921660a083015261ffff1660c090910152949350505050565b6001600160601b0388811682526001600160a01b038881166020840152908716604083015285811660608301528416608082015267ffffffffffffffff831660a08201526101408101613df760c0830184613752565b98975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561099c5761099c613e03565b5f60208284031215613e3a575f80fd5b5051919050565b5f60208284031215613e51575f80fd5b815167ffffffffffffffff811115613e67575f80fd5b8201601f81018413613e77575f80fd5b8051613e856136d28261368e565b818152856020838501011115613e99575f80fd5b613427826020830160208601613af0565b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613eda575f80fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0384168152604060208201525f613427604083018486613eaa565b8181038181111561099c5761099c613e03565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e19843603018112613f51575f80fd5b83018035915067ffffffffffffffff821115613f6b575f80fd5b602001915036819003821315613904575f80fd5b818382375f9101908152919050565b808202811582820484141761099c5761099c613e03565b5f6001600160a01b03808716835260606020840152613fc8606084018688613eaa565b915080841660408401525095945050505050565b5f60208284031215613fec575f80fd5b815161162981613baf565b5f815160a0845261400b60a0850182613b12565b90506001600160a01b0360208401511660208501526040830151604085015260608301516060850152608083015160808501528091505092915050565b602081525f6116296020830184613ff7565b5f6001820161406b5761406b613e03565b5060010190565b5f8251614083818460208701613af0565b919091019291505056fea164736f6c6343000814000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
-----Decoded View---------------
Arg [0] : flooring (address): 0x3eb879cc9a0Ef4C6f1d870A40ae187768c278Da2
Arg [1] : uniswapV3Router (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
Arg [2] : _WETH9 (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2
Arg [1] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Arg [2] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.