Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
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 = 3 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 getVaultFeeAtLR(uint256 lockingRatio) internal pure returns (uint256 fee, uint32 quota) { if (lockingRatio <= 50) { return (20000 ether, 1); } else if (lockingRatio <= 60) { return (40000 ether, 2); } else if (lockingRatio <= 70) { return (60000 ether, 4); } else if (lockingRatio <= 80) { return (80000 ether, 8); } else { /// note. above 80, can not redeem from the vault return (100000 ether, 10); } } /// @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) }) }); } 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); /// @notice Allow trusted caller to call specified addresses through the Contract /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param calls The encoded function data and target for each of the calls to make to this contract /// @return results The results from each of the calls passed in via calls function extMulticall(CallData[] calldata calls) external returns (bytes[] memory); }
// 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; } 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; } function extMulticall(CallData[] calldata calls) external virtual override returns (bytes[] memory) { return multicall2(calls); } /// @notice Aggregate calls, ensuring each returns success if required /// @param calls An array of CallData structs /// @return returnData An array of bytes function multicall2(CallData[] calldata calls) internal returns (bytes[] memory) { bytes[] memory results = new bytes[](calls.length); CallData calldata calli; for (uint256 i = 0; i < calls.length;) { calli = calls[i]; (bool success, bytes memory result) = calli.target.call(calli.callData); 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":"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":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct IMulticall.CallData[]","name":"calls","type":"tuple[]"}],"name":"extMulticall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"nonpayable","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
61010060408190523060a05262004296388190039081908339810160408190526200002a9162000064565b6001600160a01b0392831660805290821660c0521660e052620000ab565b80516001600160a01b03811681146200005f575f80fd5b919050565b5f805f6060848603121562000077575f80fd5b620000828462000048565b9250620000926020850162000048565b9150620000a26040850162000048565b90509250925092565b60805160a05160c05160e0516140bb620001db5f395f818161020c015281816104e301528181611077015281816111270152612e4301525f81816101d8015281816105b101528181611c7701528181611de401528181612ea701528181612f2101528181612fab0152612ffb01525f81816128dd015281816129060152612ab701525f81816104850152818161085a0152818161099701528181610b8d01528181610c7201528181610d4901528181610f7301528181611218015281816113d0015281816114a30152818161155c015281816116bd015281816118f50152818161199d01528181611c4d01528181611cf001528181611f1c01528181611fc5015281816122130152818161229b01528181612326015281816123b7015281816124f8015261269501526140bb5ff3fe6080604052600436106101c8575f3560e01c8063735de9f7116100f2578063ac9650d811610092578063deefbf8711610062578063deefbf871461076c578063e2c6e4381461077f578063ea5eda32146107ae578063ef2d2427146107e0575f80fd5b8063ac9650d8146106b9578063ad3cb1cc146106d8578063c660093d1461072d578063c999b80e14610740575f80fd5b80638129fc1c116100cd5780638129fc1c1461062f578063824d3575146106435780638da5cb5b1461066f57806397e4ee2a1461068d575f80fd5b8063735de9f7146105a0578063762a66a2146105d357806376c9075714610607575f80fd5b80633c777f41116101685780634f67caa7116101385780634f67caa71461051857806352d1902d1461054e5780635818ea1c14610562578063725d33b014610581575f80fd5b80633c777f411461047457806349404b7c146104bf5780634aa4a4fc146104d25780634f1ef28614610505575f80fd5b80631f0c602d116101a35780631f0c602d146102e857806321dfa77b1461036457806329e81d71146103ee578063316d1a211461041a575f80fd5b80631049334f1461025357806313af403514610285578063150b7a02146102a4575f80fd5b3661024f57336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480159061022f5750336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614155b1561024d57604051639f5c13f160e01b815260040160405180910390fd5b005b5f80fd5b34801561025e575f80fd5b5061027261026d36600461344c565b610812565b6040519081526020015b60405180910390f35b348015610290575f80fd5b5061024d61029f36600461347d565b61092d565b3480156102af575f80fd5b506102cf6102be366004613496565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161027c565b3480156102f3575f80fd5b5061030761030236600461347d565b61098c565b604080516001600160a01b039099168952602089019790975267ffffffffffffffff9586169688019690965292841660608701529083166080860152821660a08501521660c083015263ffffffff1660e08201526101000161027c565b34801561036f575f80fd5b5061038361037e366004613529565b610abe565b604080519687526001600160a01b0390951660208088019190915263ffffffff9485168787015292841660608701529216608085015281516001600160601b031660a085015281015167ffffffffffffffff1660c0840152015160ff1660e08201526101000161027c565b3480156103f9575f80fd5b5061040d61040836600461344c565b610d3e565b60405161027c9190613562565b348015610425575f80fd5b5061043961043436600461360d565b610f04565b60408051825167ffffffffffffffff16815260208084015163ffffffff1690820152918101516001600160a01b03169082015260600161027c565b34801561047f575f80fd5b506104a77f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161027c565b61024d6104cd366004613635565b611060565b3480156104dd575f80fd5b506104a77f000000000000000000000000000000000000000000000000000000000000000081565b61024d610513366004613714565b611196565b348015610523575f80fd5b5061053761053236600461360d565b6111b5565b60405161027c9b9a999897969594939291906137a5565b348015610559575f80fd5b5061027261139e565b34801561056d575f80fd5b506104a761057c36600461347d565b6113cc565b34801561058c575f80fd5b506104a761059b36600461347d565b61149f565b3480156105ab575f80fd5b506104a77f000000000000000000000000000000000000000000000000000000000000000081565b3480156105de575f80fd5b506105f26105ed36600461360d565b6114f8565b60405161027c99989796959493929190613832565b61061a6106153660046139a9565b6116b9565b6040805192835260208301919091520161027c565b34801561063a575f80fd5b5061024d611755565b34801561064e575f80fd5b5061066261065d366004613a43565b611898565b60405161027c9190613aac565b34801561067a575f80fd5b505f546104a7906001600160a01b031681565b348015610698575f80fd5b506106ac6106a7366004613abe565b611ae0565b60405161027c9190613b4a565b3480156106c4575f80fd5b506106ac6106d3366004613abe565b611aec565b3480156106e3575f80fd5b506107206040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161027c9190613baa565b61027261073b366004613bc9565b611c23565b34801561074b575f80fd5b5061075f61075a366004613c52565b611e76565b60405161027c9190613c88565b61061a61077a366004613cf5565b6121e8565b34801561078a575f80fd5b5061079e61079936600461347d565b6123b3565b604051901515815260200161027c565b3480156107b9575f80fd5b506107cd6107c836600461347d565b612488565b60405161027c9796959493929190613d55565b3480156107eb575f80fd5b506107ff6107fa36600461360d565b612633565b60405161027c9796959493929190613dae565b604080516001600160a01b038416602080830191909152606682840152825180830384018152606090920190925280519101205f9081610853826004613e24565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf86846040516020016108ae9291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016108e291815260200190565b602060405180830381865afa1580156108fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109219190613e37565b93505050505b92915050565b6109356127ed565b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b5f805f805f805f805f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8b60656040516020016109ec9291906001600160a01b03929092168252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600960248201526044015f60405180830381865afa158015610a3f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a669190810190613e4e565b6020810151606082015161010083015161012090930151919d909c5067ffffffffffffffff8084169c50604084811c82169c50608085901c82169b5060c09490941c995082169750911c63ffffffff16945092505050565b60408051606080820183525f808352602080840182905283850182905284516001600160a01b03891681830152606681870152855180820387018152930190945281519190930120829182918291829182610b188a612818565b610b23836003613e24565b604080516001600160a01b03909316602084015282015260600160408051601f1981840301815282825280516020918201209083018c905290820181905291505f9060600160408051601f19818403018152919052805160209091012090505f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166335fd631a610bbd856001613e24565b60405160e083901b6001600160e01b03191681526004810191909152600260248201526044015f60405180830381865afa158015610bfd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610c249190810190613e4e565b905060208101516001600160601b0381169a506001600160a01b038160601c1699506040820151905063ffffffff8116985063ffffffff8160201c16975063ffffffff8160401c169650505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf846040518263ffffffff1660e01b8152600401610cbe91815260200190565b602060405180830381865afa158015610cd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfd9190613e37565b6001600160601b038116875267ffffffffffffffff606082901c16602088015260a01c60ff16604087015250989c979b509599509397509195509392505050565b610d46613385565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a84866069604051602001610d9f9291906001600160a01b03929092168252602082015260400190565b60408051601f1981840301815282825280516020918201206001600160a01b039094169083015281019190915260600160408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600360248201526044015f60405180830381865afa158015610e22573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e499190810190613e4e565b602080820151604080840151606094850151825160e0810184526001600160a01b0380861682890190815261ffff60a088811c821660808087019190915260b08a811c84168388015260c09a8b1c84168b88015293865288518083018a52858916815288831c8416818d01529388901c8316848a01529887901c82169a83019a909a5260d09590951c85169681019690965281870195909552835180850185529482168552951c169282019290925290820152949350505050565b604080516060810182525f8082526020820181905291810182905290610f2984612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f610f6c826003613e24565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf8684604051602001610fbc929190918252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610ff091815260200190565b602060405180830381865afa15801561100b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102f9190613e37565b67ffffffffffffffff81168552604081811c63ffffffff16602087015260609190911c908501525091949350505050565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156110c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e89190613e37565b90508281101561110b5760405163409a171f60e01b815260040160405180910390fd5b801561119157604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024015f604051808303815f87803b158015611170575f80fd5b505af1158015611182573d5f803e3d5ffd5b505050506111915f838361283a565b505050565b61119e6128d2565b6111a782612989565b6111b18282612994565b5050565b5f805f805f805f805f806111c7613410565b5f6111d18e612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f198184030181529190528051602090910120611211906005613e24565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8f84604051602001611261929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156112b4573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112db9190810190613e4e565b90505f80602083015165ffffffffffff81169f5065ffffffffffff8160301c169e506001600160a01b038160601c169d50604084015190506001600160a01b03811699506001600160601b038160a01c169c506060840151905067ffffffffffffffff81169a506001600160601b038160401c169b5065ffffffffffff8160a01c16985060ff8160d01c169750506080830151955060a0830151915060c083015190506113888282612a68565b9450505050509295989b509295989b9093969950565b5f6113a7612aac565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf8460656040516020016114259291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161145991815260200190565b602060405180830381865afa158015611474573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114989190613e37565b9392505050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf8460686040516020016114259291906001600160a01b03929092168252602082015260400190565b5f805f805f805f80611508613410565b5f6115128c612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611555826004613e24565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8e846040516020016115a5929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156115f8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261161f9190810190613e4e565b90505f8060208301516001600160601b0381169e508060601c9d50604084015190506001600160601b0381169c508060601c9950606084015190506001600160601b0381169b508060601c9a506080840151905067ffffffffffffffff8160081c16985060ff8160681c1697505060a0830151915060c083015190506116a58282612a68565b955050505050509295985092959850929598565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166364d5d9fa8a8a8a6040518463ffffffff1660e01b815260040161170b93929190613f00565b5f604051808303815f87803b158015611722575f80fd5b505af1158015611734573d5f803e3d5ffd5b5050505061174589878787876121e8565b9150915097509795505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f8115801561179f5750825b90505f8267ffffffffffffffff1660011480156117bb5750303b155b9050811580156117c9575080155b156117e75760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561181b57845468ff00000000000000001916680100000000000000001785555b61183e5f805473ffffffffffffffffffffffffffffffffffffffff191633179055565b611846612af5565b831561189157845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b604080516001600160a01b038516602080830191909152606582840152825180830384018152606092830190935282519201919091205f6118da826002613e24565b604051631e2eaeaf60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631e2eaeaf90602401602060405180830381865afa158015611942573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119669190613e37565b90508086101580611975575084155b1561198257505050611498565b5f61198d8783613f22565b90508086101561199a5750845b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a89866040516020016119de91815260200190565b604051602081830303815290604052805190602001205f1c611a009190613e24565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa158015611a40573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a679190810190613e4e565b90508167ffffffffffffffff811115611a8257611a82613656565b604051908082528060200260200182016040528015611aab578160200160208202803683370190505b50955060208083600101025b80821015611ad2578183015182890152602082019150611ab7565b505050505050509392505050565b60606114988383612afd565b60605f8267ffffffffffffffff811115611b0857611b08613656565b604051908082528060200260200182016040528015611b3b57816020015b6060815260200190600190039081611b265790505b5090505f5b83811015611c1b575f8030878785818110611b5d57611b5d613f35565b9050602002810190611b6f9190613f49565b604051611b7d929190613f8c565b5f60405180830381855af49150503d805f8114611bb5576040519150601f19603f3d011682016040523d82523d5f602084013e611bba565b606091505b50915091508115611be85780848481518110611bd857611bd8613f35565b6020026020010181905250611c11565b805115611bf85780518082602001fd5b6040516302cf089f60e51b815260040160405180910390fd5b5050600101611b40565b509392505050565b5f80611c3969d3c21bcecceda100000086613f9b565b90505f611c45886113cc565b9050611c71887f0000000000000000000000000000000000000000000000000000000000000000612c2e565b611c9c817f000000000000000000000000000000000000000000000000000000000000000084612d08565b611cda8833308a8a808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250612dff92505050565b60405162e592a960e61b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633964aa4090611d2b908b908b908b903390600401613fb2565b5f604051808303815f87803b158015611d42575f80fd5b505af1158015611d54573d5f803e3d5ffd5b50506040516323b872dd60e01b8152336004820152306024820152604481018590526001600160a01b03841692506323b872dd91506064016020604051808303815f875af1158015611da8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dcc9190613fe9565b5060405163c04b8d5960e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c04b8d5990611e19908790600401614055565b6020604051808303815f875af1158015611e35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e599190613e37565b92508415611e6b57611e6b8333611060565b505095945050505050565b60605f611e8286612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611ec5826005613e24565b60408051602081018990529081018290529091505f9060600160408051601f198184030181529190528051602090910120611f01906003613e24565b604051631e2eaeaf60e01b8152600481018290529091505f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631e2eaeaf90602401602060405180830381865afa158015611f69573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f8d9190613e37565b90508087101580611f9c575085155b15611faa57505050506121e0565b5f611fb58883613f22565b905080871015611fc25750855b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8a8660405160200161200691815260200190565b604051602081830303815290604052805190602001205f1c6120289190613e24565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa158015612068573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261208f9190810190613e4e565b90508167ffffffffffffffff8111156120aa576120aa613656565b6040519080825280602002602001820160405280156120f357816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816120c85790505b5096505f5b828110156121d8575f6020600183010283015190506001600160a01b03811689838151811061212957612129613f35565b60200260200101515f01906001600160a01b031690816001600160a01b03168152505065ffffffffffff60a082901c1689838151811061216b5761216b613f35565b60200260200101516020019065ffffffffffff16908165ffffffffffff168152505065ffffffffffff60d082901c168983815181106121ac576121ac613f35565b602090810291909101015165ffffffffffff909116604090910152506121d181614067565b90506120f8565b505050505050505b949350505050565b5f80806121ff69d3c21bcecceda100000088613f9b565b90505f61220b896113cc565b9050612238817f000000000000000000000000000000000000000000000000000000000000000084612d08565b612243338787612e40565b93505f82866060015111612257575f612267565b8286606001516122679190613f22565b905080156122f3576040516346d5785160e11b81523060048201526001600160a01b038381166024830152604482018390527f00000000000000000000000000000000000000000000000000000000000000001690638daaf0a2906064015f604051808303815f87803b1580156122dc575f80fd5b505af11580156122ee573d5f803e3d5ffd5b505050505b60405163fdbed69960e01b81526001600160a01b038b81166004830152602482018b9052604482018a90523360648301527f0000000000000000000000000000000000000000000000000000000000000000169063fdbed699906084016020604051808303815f875af115801561236c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123909190613e37565b935080158061239e57508084145b6123a6575f80fd5b5050509550959350505050565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316631e2eaeaf84606760405160200161240c9291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161244091815260200190565b602060405180830381865afa15801561245b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061247f9190613e37565b15159392505050565b5f805f60605f805f808860666040516020016124b99291906001600160a01b03929092168252602082015260400190565b60408051601f19818403018152908290528051602090910120631afeb18d60e11b8252600482018190526006602483015291505f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906335fd631a906044015f60405180830381865afa15801561253c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125639190810190613e4e565b602080820151604083015160608085015160c08601516001600160601b0385169f509390911c9c50985063ffffffff82169750911c61ffff16945090915060086040519080825280602002602001820160405280156125cc578160200160208202803683370190505b50965060f081901c60ff1697505f5b6008811015612624576125ef816018613f9b565b82901c62ffffff1688828151811061260957612609613f35565b602090810291909101015261261d81614067565b90506125db565b50505050919395979092949650565b5f805f805f80612641613410565b5f61264b8a612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f61268e826006613e24565b5f1b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166335fd631a8c846040516020016126de929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600560248201526044015f60405180830381865afa158015612731573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526127589190810190613e4e565b90505f8060208301516001600160601b0381169c506001600160a01b038160601c169b50604084015190506001600160601b0381169a506001600160a01b038160601c169950606084015190506001600160a01b038116985067ffffffffffffffff8160a01c169750506080830151915060a083015190506127da8282612a68565b9550505050505092959891949750929550565b5f546001600160a01b03163314612816576040516282b42960e81b815260040160405180910390fd5b565b5f806128238361149f565b90506001600160a01b038116610927575090919050565b5f6001600160a01b038416612876575f805f8085875af190508061287157604051633d2cec6f60e21b815260040160405180910390fd5b6128cc565b60405163a9059cbb60e01b5f52836004528260245260205f60445f80895af13d15601f3d1160015f511416171691505f6060528060405250806128cc57604051633c9fd93960e21b815260040160405180910390fd5b50505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061296b57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661295f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156128165760405163703e46dd60e11b815260040160405180910390fd5b6129916127ed565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156129ee575060408051601f3d908101601f191682019092526129eb91810190613e37565b60015b612a1b57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612a5e57604051632a87526960e21b815260048101829052602401612a12565b6111918383613098565b612a70613410565b80516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146128165760405163703e46dd60e11b815260040160405180910390fd5b6128166130ed565b60605f8267ffffffffffffffff811115612b1957612b19613656565b604051908082528060200260200182016040528015612b4c57816020015b6060815260200190600190039081612b375790505b509050365f5b84811015612c2457858582818110612b6c57612b6c613f35565b9050602002810190612b7e919061407f565b91505f80612b8f602085018561347d565b6001600160a01b0316612ba56020860186613f49565b604051612bb3929190613f8c565b5f604051808303815f865af19150503d805f8114612bec576040519150601f19603f3d011682016040523d82523d5f602084013e612bf1565b606091505b50915091508115611be85780858481518110612c0f57612c0f613f35565b60200260200101819052505050600101612b52565b5090949350505050565b60405163e985e9c560e01b81523060048201526001600160a01b0382811660248301525f919084169063e985e9c590604401602060405180830381865afa158015612c7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c9f9190613fe9565b9050806111915760405163a22cb46560e01b81526001600160a01b0383811660048301526001602483015284169063a22cb465906044015f604051808303815f87803b158015612ced575f80fd5b505af1158015612cff573d5f803e3d5ffd5b50505050505050565b805f03612d1457505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015612d61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d859190613e37565b9050818110156128cc5760405163095ea7b360e01b81526001600160a01b0384811660048301525f19602483015285169063095ea7b3906044016020604051808303815f875af1158015612ddb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118919190613fe9565b80515f5b81811015612e3857612e30868686868581518110612e2357612e23613f35565b602002602001015161313b565b600101612e03565b505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316148015612e86575081608001514710155b15612fa5576080820151604051631e51809360e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163f28c049891612edc908690600401614055565b60206040518083038185885af1158015612ef8573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190612f1d9190613e37565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166312210e8a6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612f77575f80fd5b505af1158015612f89573d5f803e3d5ffd5b505050505f471115612fa057612fa05f854761283a565b611498565b612fd4837f00000000000000000000000000000000000000000000000000000000000000008460800151612d08565b612fe48385308560800151613196565b604051631e51809360e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f28c049890613030908590600401614055565b6020604051808303815f875af115801561304c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130709190613e37565b905080826080015111156114985761149883858385608001516130939190613f22565b61283a565b6130a1826131f1565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156130e5576111918282613274565b6111b16132e6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661281657604051631afcd79f60e31b815260040160405180910390fd5b5f604051632142170760e11b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f60605280604052508061189157604051636ff8a60f60e11b815260040160405180910390fd5b5f6040516323b872dd60e01b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f60605280604052508061189157604051633c9fd93960e21b815260040160405180910390fd5b806001600160a01b03163b5f0361322657604051634c9c8ce360e01b81526001600160a01b0382166004820152602401612a12565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b031684604051613290919061409d565b5f60405180830381855af49150503d805f81146132c8576040519150601f19603f3d011682016040523d82523d5f602084013e6132cd565b606091505b50915091506132dd858383613305565b95945050505050565b34156128165760405163b398979f60e01b815260040160405180910390fd5b60608261331557612fa08261335c565b815115801561332c57506001600160a01b0384163b155b1561335557604051639996b31560e01b81526001600160a01b0385166004820152602401612a12565b5080611498565b80511561336c5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6040805160e081019091525f606082018181526080830182905260a0830182905260c0830191909152819081526040805160a0810182525f80825260208281018290529282018190526060820181905260808201529101905b815260200161340b60405180604001604052805f6001600160a01b031681526020015f61ffff1681525090565b905290565b604080516080810182525f91810182815260608201929092529081906133de565b80356001600160a01b0381168114613447575f80fd5b919050565b5f806040838503121561345d575f80fd5b61346683613431565b915061347460208401613431565b90509250929050565b5f6020828403121561348d575f80fd5b61149882613431565b5f805f805f608086880312156134aa575f80fd5b6134b386613431565b94506134c160208701613431565b935060408601359250606086013567ffffffffffffffff808211156134e4575f80fd5b818801915088601f8301126134f7575f80fd5b813581811115613505575f80fd5b896020828501011115613516575f80fd5b9699959850939650602001949392505050565b5f805f6060848603121561353b575f80fd5b61354484613431565b925061355260208501613431565b9150604084013590509250925092565b815180516001600160a01b03908116835260208083015161ffff9081168286015260408085015182168187015260609485015182168587015282870151805190941660808088019190915292840151821660a087015283810151821660c087015293830151811660e08601529101511661010083015282015161016082019061360661012084018280516001600160a01b0316825260209081015161ffff16910152565b5092915050565b5f806040838503121561361e575f80fd5b61362783613431565b946020939093013593505050565b5f8060408385031215613646575f80fd5b8235915061347460208401613431565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561369357613693613656565b604052919050565b5f67ffffffffffffffff8211156136b4576136b4613656565b50601f01601f191660200190565b5f82601f8301126136d1575f80fd5b81356136e46136df8261369b565b61366a565b8181528460208386010111156136f8575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613725575f80fd5b61372e83613431565b9150602083013567ffffffffffffffff811115613749575f80fd5b613755858286016136c2565b9150509250929050565b61378182825180516001600160a01b0316825260209081015161ffff16910152565b60209081015180516001600160a01b03166040840152015161ffff16606090910152565b65ffffffffffff8c811682528b811660208301526001600160a01b038b811660408401526001600160601b038b811660608501528a16608084015267ffffffffffffffff891660a0840152871660c0830152851660e082015283151561010082015261012081018390526101c0810161382261014083018461375f565b9c9b505050505050505050505050565b6001600160601b038a1681526001600160a01b0389811660208301526fffffffffffffffffffffffffffffffff8981166040840152881660608301528681166080830152851660a082015267ffffffffffffffff841660c08201526101808101600384106138ae57634e487b7160e01b5f52602160045260245ffd5b8360e08301526138c261010083018461375f565b9a9950505050505050505050565b5f8083601f8401126138e0575f80fd5b50813567ffffffffffffffff8111156138f7575f80fd5b6020830191508360208260051b8501011115613911575f80fd5b9250929050565b5f60a08284031215613928575f80fd5b60405160a0810167ffffffffffffffff828210818311171561394c5761394c613656565b816040528293508435915080821115613963575f80fd5b50613970858286016136c2565b82525061397f60208401613431565b60208201526040830135604082015260608301356060820152608083013560808201525092915050565b5f805f805f805f60c0888a0312156139bf575f80fd5b6139c888613431565b9650602088013567ffffffffffffffff808211156139e4575f80fd5b6139f08b838c016138d0565b909850965060408a0135955060608a01359450869150613a1260808b01613431565b935060a08a0135915080821115613a27575f80fd5b50613a348a828b01613918565b91505092959891949750929550565b5f805f60608486031215613a55575f80fd5b613a5e84613431565b95602085013595506040909401359392505050565b5f8151808452602080850194508084015f5b83811015613aa157815187529582019590820190600101613a85565b509495945050505050565b602081525f6114986020830184613a73565b5f8060208385031215613acf575f80fd5b823567ffffffffffffffff811115613ae5575f80fd5b613af1858286016138d0565b90969095509350505050565b5f5b83811015613b17578181015183820152602001613aff565b50505f910152565b5f8151808452613b36816020860160208601613afd565b601f01601f19169290920160200192915050565b5f602080830181845280855180835260408601915060408160051b87010192508387015f5b82811015613b9d57603f19888603018452613b8b858351613b1f565b94509285019290850190600101613b6f565b5092979650505050505050565b602081525f6114986020830184613b1f565b8015158114612991575f80fd5b5f805f805f60808688031215613bdd575f80fd5b613be686613431565b9450602086013567ffffffffffffffff80821115613c02575f80fd5b613c0e89838a016138d0565b909650945060408801359150613c2382613bbc565b90925060608701359080821115613c38575f80fd5b50613c4588828901613918565b9150509295509295909350565b5f805f8060808587031215613c65575f80fd5b613c6e85613431565b966020860135965060408601359560600135945092505050565b602080825282518282018190525f919060409081850190868401855b82811015613ce857815180516001600160a01b031685528681015165ffffffffffff9081168887015290860151168585015260609093019290850190600101613ca4565b5091979650505050505050565b5f805f805f60a08688031215613d09575f80fd5b613d1286613431565b94506020860135935060408601359250613d2e60608701613431565b9150608086013567ffffffffffffffff811115613d49575f80fd5b613c4588828901613918565b8781526001600160a01b038716602082015260ff8616604082015260e060608201525f613d8560e0830187613a73565b60808301959095525063ffffffff9290921660a083015261ffff1660c090910152949350505050565b6001600160601b0388811682526001600160a01b038881166020840152908716604083015285811660608301528416608082015267ffffffffffffffff831660a08201526101408101613e0460c083018461375f565b98975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561092757610927613e10565b5f60208284031215613e47575f80fd5b5051919050565b5f60208284031215613e5e575f80fd5b815167ffffffffffffffff811115613e74575f80fd5b8201601f81018413613e84575f80fd5b8051613e926136df8261369b565b818152856020838501011115613ea6575f80fd5b6132dd826020830160208601613afd565b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613ee7575f80fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0384168152604060208201525f6132dd604083018486613eb7565b8181038181111561092757610927613e10565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e19843603018112613f5e575f80fd5b83018035915067ffffffffffffffff821115613f78575f80fd5b602001915036819003821315613911575f80fd5b818382375f9101908152919050565b808202811582820484141761092757610927613e10565b5f6001600160a01b03808716835260606020840152613fd5606084018688613eb7565b915080841660408401525095945050505050565b5f60208284031215613ff9575f80fd5b815161149881613bbc565b5f815160a0845261401860a0850182613b1f565b90506001600160a01b0360208401511660208501526040830151604085015260608301516060850152608083015160808501528091505092915050565b602081525f6114986020830184614004565b5f6001820161407857614078613e10565b5060010190565b5f8235603e19833603018112614093575f80fd5b9190910192915050565b5f8251614093818460208701613afd56fea164736f6c6343000814000a0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Deployed Bytecode
0x6080604052600436106101c8575f3560e01c8063735de9f7116100f2578063ac9650d811610092578063deefbf8711610062578063deefbf871461076c578063e2c6e4381461077f578063ea5eda32146107ae578063ef2d2427146107e0575f80fd5b8063ac9650d8146106b9578063ad3cb1cc146106d8578063c660093d1461072d578063c999b80e14610740575f80fd5b80638129fc1c116100cd5780638129fc1c1461062f578063824d3575146106435780638da5cb5b1461066f57806397e4ee2a1461068d575f80fd5b8063735de9f7146105a0578063762a66a2146105d357806376c9075714610607575f80fd5b80633c777f41116101685780634f67caa7116101385780634f67caa71461051857806352d1902d1461054e5780635818ea1c14610562578063725d33b014610581575f80fd5b80633c777f411461047457806349404b7c146104bf5780634aa4a4fc146104d25780634f1ef28614610505575f80fd5b80631f0c602d116101a35780631f0c602d146102e857806321dfa77b1461036457806329e81d71146103ee578063316d1a211461041a575f80fd5b80631049334f1461025357806313af403514610285578063150b7a02146102a4575f80fd5b3661024f57336001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564161480159061022f5750336001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21614155b1561024d57604051639f5c13f160e01b815260040160405180910390fd5b005b5f80fd5b34801561025e575f80fd5b5061027261026d36600461344c565b610812565b6040519081526020015b60405180910390f35b348015610290575f80fd5b5061024d61029f36600461347d565b61092d565b3480156102af575f80fd5b506102cf6102be366004613496565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161027c565b3480156102f3575f80fd5b5061030761030236600461347d565b61098c565b604080516001600160a01b039099168952602089019790975267ffffffffffffffff9586169688019690965292841660608701529083166080860152821660a08501521660c083015263ffffffff1660e08201526101000161027c565b34801561036f575f80fd5b5061038361037e366004613529565b610abe565b604080519687526001600160a01b0390951660208088019190915263ffffffff9485168787015292841660608701529216608085015281516001600160601b031660a085015281015167ffffffffffffffff1660c0840152015160ff1660e08201526101000161027c565b3480156103f9575f80fd5b5061040d61040836600461344c565b610d3e565b60405161027c9190613562565b348015610425575f80fd5b5061043961043436600461360d565b610f04565b60408051825167ffffffffffffffff16815260208084015163ffffffff1690820152918101516001600160a01b03169082015260600161027c565b34801561047f575f80fd5b506104a77f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da281565b6040516001600160a01b03909116815260200161027c565b61024d6104cd366004613635565b611060565b3480156104dd575f80fd5b506104a77f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b61024d610513366004613714565b611196565b348015610523575f80fd5b5061053761053236600461360d565b6111b5565b60405161027c9b9a999897969594939291906137a5565b348015610559575f80fd5b5061027261139e565b34801561056d575f80fd5b506104a761057c36600461347d565b6113cc565b34801561058c575f80fd5b506104a761059b36600461347d565b61149f565b3480156105ab575f80fd5b506104a77f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b3480156105de575f80fd5b506105f26105ed36600461360d565b6114f8565b60405161027c99989796959493929190613832565b61061a6106153660046139a9565b6116b9565b6040805192835260208301919091520161027c565b34801561063a575f80fd5b5061024d611755565b34801561064e575f80fd5b5061066261065d366004613a43565b611898565b60405161027c9190613aac565b34801561067a575f80fd5b505f546104a7906001600160a01b031681565b348015610698575f80fd5b506106ac6106a7366004613abe565b611ae0565b60405161027c9190613b4a565b3480156106c4575f80fd5b506106ac6106d3366004613abe565b611aec565b3480156106e3575f80fd5b506107206040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b60405161027c9190613baa565b61027261073b366004613bc9565b611c23565b34801561074b575f80fd5b5061075f61075a366004613c52565b611e76565b60405161027c9190613c88565b61061a61077a366004613cf5565b6121e8565b34801561078a575f80fd5b5061079e61079936600461347d565b6123b3565b604051901515815260200161027c565b3480156107b9575f80fd5b506107cd6107c836600461347d565b612488565b60405161027c9796959493929190613d55565b3480156107eb575f80fd5b506107ff6107fa36600461360d565b612633565b60405161027c9796959493929190613dae565b604080516001600160a01b038416602080830191909152606682840152825180830384018152606090920190925280519101205f9081610853826004613e24565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf86846040516020016108ae9291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004016108e291815260200190565b602060405180830381865afa1580156108fd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109219190613e37565b93505050505b92915050565b6109356127ed565b5f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b5f805f805f805f805f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8b60656040516020016109ec9291906001600160a01b03929092168252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600960248201526044015f60405180830381865afa158015610a3f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a669190810190613e4e565b6020810151606082015161010083015161012090930151919d909c5067ffffffffffffffff8084169c50604084811c82169c50608085901c82169b5060c09490941c995082169750911c63ffffffff16945092505050565b60408051606080820183525f808352602080840182905283850182905284516001600160a01b03891681830152606681870152855180820387018152930190945281519190930120829182918291829182610b188a612818565b610b23836003613e24565b604080516001600160a01b03909316602084015282015260600160408051601f1981840301815282825280516020918201209083018c905290820181905291505f9060600160408051601f19818403018152919052805160209091012090505f6001600160a01b037f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2166335fd631a610bbd856001613e24565b60405160e083901b6001600160e01b03191681526004810191909152600260248201526044015f60405180830381865afa158015610bfd573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610c249190810190613e4e565b905060208101516001600160601b0381169a506001600160a01b038160601c1699506040820151905063ffffffff8116985063ffffffff8160201c16975063ffffffff8160401c169650505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf846040518263ffffffff1660e01b8152600401610cbe91815260200190565b602060405180830381865afa158015610cd9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfd9190613e37565b6001600160601b038116875267ffffffffffffffff606082901c16602088015260a01c60ff16604087015250989c979b509599509397509195509392505050565b610d46613385565b5f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a84866069604051602001610d9f9291906001600160a01b03929092168252602082015260400190565b60408051601f1981840301815282825280516020918201206001600160a01b039094169083015281019190915260600160408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600360248201526044015f60405180830381865afa158015610e22573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e499190810190613e4e565b602080820151604080840151606094850151825160e0810184526001600160a01b0380861682890190815261ffff60a088811c821660808087019190915260b08a811c84168388015260c09a8b1c84168b88015293865288518083018a52858916815288831c8416818d01529388901c8316848a01529887901c82169a83019a909a5260d09590951c85169681019690965281870195909552835180850185529482168552951c169282019290925290820152949350505050565b604080516060810182525f8082526020820181905291810182905290610f2984612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f610f6c826003613e24565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf8684604051602001610fbc929190918252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b8152600401610ff091815260200190565b602060405180830381865afa15801561100b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102f9190613e37565b67ffffffffffffffff81168552604081811c63ffffffff16602087015260609190911c908501525091949350505050565b6040516370a0823160e01b81523060048201525f907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316906370a0823190602401602060405180830381865afa1580156110c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e89190613e37565b90508281101561110b5760405163409a171f60e01b815260040160405180910390fd5b801561119157604051632e1a7d4d60e01b8152600481018290527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031690632e1a7d4d906024015f604051808303815f87803b158015611170575f80fd5b505af1158015611182573d5f803e3d5ffd5b505050506111915f838361283a565b505050565b61119e6128d2565b6111a782612989565b6111b18282612994565b5050565b5f805f805f805f805f806111c7613410565b5f6111d18e612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f198184030181529190528051602090910120611211906005613e24565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8f84604051602001611261929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156112b4573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526112db9190810190613e4e565b90505f80602083015165ffffffffffff81169f5065ffffffffffff8160301c169e506001600160a01b038160601c169d50604084015190506001600160a01b03811699506001600160601b038160a01c169c506060840151905067ffffffffffffffff81169a506001600160601b038160401c169b5065ffffffffffff8160a01c16985060ff8160d01c169750506080830151955060a0830151915060c083015190506113888282612a68565b9450505050509295989b509295989b9093969950565b5f6113a7612aac565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf8460656040516020016114259291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161145991815260200190565b602060405180830381865afa158015611474573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114989190613e37565b9392505050565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf8460686040516020016114259291906001600160a01b03929092168252602082015260400190565b5f805f805f805f80611508613410565b5f6115128c612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611555826004613e24565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8e846040516020016115a5929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600660248201526044015f60405180830381865afa1580156115f8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261161f9190810190613e4e565b90505f8060208301516001600160601b0381169e508060601c9d50604084015190506001600160601b0381169c508060601c9950606084015190506001600160601b0381169b508060601c9a506080840151905067ffffffffffffffff8160081c16985060ff8160681c1697505060a0830151915060c083015190506116a58282612a68565b955050505050509295985092959850929598565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166364d5d9fa8a8a8a6040518463ffffffff1660e01b815260040161170b93929190613f00565b5f604051808303815f87803b158015611722575f80fd5b505af1158015611734573d5f803e3d5ffd5b5050505061174589878787876121e8565b9150915097509795505050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f8115801561179f5750825b90505f8267ffffffffffffffff1660011480156117bb5750303b155b9050811580156117c9575080155b156117e75760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561181b57845468ff00000000000000001916680100000000000000001785555b61183e5f805473ffffffffffffffffffffffffffffffffffffffff191633179055565b611846612af5565b831561189157845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050565b604080516001600160a01b038516602080830191909152606582840152825180830384018152606092830190935282519201919091205f6118da826002613e24565b604051631e2eaeaf60e01b8152600481018290529091505f907f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b031690631e2eaeaf90602401602060405180830381865afa158015611942573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119669190613e37565b90508086101580611975575084155b1561198257505050611498565b5f61198d8783613f22565b90508086101561199a5750845b5f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a89866040516020016119de91815260200190565b604051602081830303815290604052805190602001205f1c611a009190613e24565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa158015611a40573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a679190810190613e4e565b90508167ffffffffffffffff811115611a8257611a82613656565b604051908082528060200260200182016040528015611aab578160200160208202803683370190505b50955060208083600101025b80821015611ad2578183015182890152602082019150611ab7565b505050505050509392505050565b60606114988383612afd565b60605f8267ffffffffffffffff811115611b0857611b08613656565b604051908082528060200260200182016040528015611b3b57816020015b6060815260200190600190039081611b265790505b5090505f5b83811015611c1b575f8030878785818110611b5d57611b5d613f35565b9050602002810190611b6f9190613f49565b604051611b7d929190613f8c565b5f60405180830381855af49150503d805f8114611bb5576040519150601f19603f3d011682016040523d82523d5f602084013e611bba565b606091505b50915091508115611be85780848481518110611bd857611bd8613f35565b6020026020010181905250611c11565b805115611bf85780518082602001fd5b6040516302cf089f60e51b815260040160405180910390fd5b5050600101611b40565b509392505050565b5f80611c3969d3c21bcecceda100000086613f9b565b90505f611c45886113cc565b9050611c71887f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2612c2e565b611c9c817f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156484612d08565b611cda8833308a8a808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250612dff92505050565b60405162e592a960e61b81526001600160a01b037f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da21690633964aa4090611d2b908b908b908b903390600401613fb2565b5f604051808303815f87803b158015611d42575f80fd5b505af1158015611d54573d5f803e3d5ffd5b50506040516323b872dd60e01b8152336004820152306024820152604481018590526001600160a01b03841692506323b872dd91506064016020604051808303815f875af1158015611da8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dcc9190613fe9565b5060405163c04b8d5960e01b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169063c04b8d5990611e19908790600401614055565b6020604051808303815f875af1158015611e35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e599190613e37565b92508415611e6b57611e6b8333611060565b505095945050505050565b60605f611e8286612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f611ec5826005613e24565b60408051602081018990529081018290529091505f9060600160408051601f198184030181529190528051602090910120611f01906003613e24565b604051631e2eaeaf60e01b8152600481018290529091505f907f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b031690631e2eaeaf90602401602060405180830381865afa158015611f69573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f8d9190613e37565b90508087101580611f9c575085155b15611faa57505050506121e0565b5f611fb58883613f22565b905080871015611fc25750855b5f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8a8660405160200161200691815260200190565b604051602081830303815290604052805190602001205f1c6120289190613e24565b60405160e083901b6001600160e01b03191681526004810191909152602481018590526044015f60405180830381865afa158015612068573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261208f9190810190613e4e565b90508167ffffffffffffffff8111156120aa576120aa613656565b6040519080825280602002602001820160405280156120f357816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816120c85790505b5096505f5b828110156121d8575f6020600183010283015190506001600160a01b03811689838151811061212957612129613f35565b60200260200101515f01906001600160a01b031690816001600160a01b03168152505065ffffffffffff60a082901c1689838151811061216b5761216b613f35565b60200260200101516020019065ffffffffffff16908165ffffffffffff168152505065ffffffffffff60d082901c168983815181106121ac576121ac613f35565b602090810291909101015165ffffffffffff909116604090910152506121d181614067565b90506120f8565b505050505050505b949350505050565b5f80806121ff69d3c21bcecceda100000088613f9b565b90505f61220b896113cc565b9050612238817f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da284612d08565b612243338787612e40565b93505f82866060015111612257575f612267565b8286606001516122679190613f22565b905080156122f3576040516346d5785160e11b81523060048201526001600160a01b038381166024830152604482018390527f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da21690638daaf0a2906064015f604051808303815f87803b1580156122dc575f80fd5b505af11580156122ee573d5f803e3d5ffd5b505050505b60405163fdbed69960e01b81526001600160a01b038b81166004830152602482018b9052604482018a90523360648301527f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da2169063fdbed699906084016020604051808303815f875af115801561236c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123909190613e37565b935080158061239e57508084145b6123a6575f80fd5b5050509550959350505050565b5f807f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b0316631e2eaeaf84606760405160200161240c9291906001600160a01b03929092168252602082015260400190565b604051602081830303815290604052805190602001206040518263ffffffff1660e01b815260040161244091815260200190565b602060405180830381865afa15801561245b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061247f9190613e37565b15159392505050565b5f805f60605f805f808860666040516020016124b99291906001600160a01b03929092168252602082015260400190565b60408051601f19818403018152908290528051602090910120631afeb18d60e11b8252600482018190526006602483015291505f906001600160a01b037f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da216906335fd631a906044015f60405180830381865afa15801561253c573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125639190810190613e4e565b602080820151604083015160608085015160c08601516001600160601b0385169f509390911c9c50985063ffffffff82169750911c61ffff16945090915060086040519080825280602002602001820160405280156125cc578160200160208202803683370190505b50965060f081901c60ff1697505f5b6008811015612624576125ef816018613f9b565b82901c62ffffff1688828151811061260957612609613f35565b602090810291909101015261261d81614067565b90506125db565b50505050919395979092949650565b5f805f805f80612641613410565b5f61264b8a612818565b604080516001600160a01b03909216602083015260659082015260600160408051601f19818403018152919052805160209091012090505f61268e826006613e24565b5f1b90505f7f0000000000000000000000003eb879cc9a0ef4c6f1d870a40ae187768c278da26001600160a01b03166335fd631a8c846040516020016126de929190918252602082015260400190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b1682526004820152600560248201526044015f60405180830381865afa158015612731573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526127589190810190613e4e565b90505f8060208301516001600160601b0381169c506001600160a01b038160601c169b50604084015190506001600160601b0381169a506001600160a01b038160601c169950606084015190506001600160a01b038116985067ffffffffffffffff8160a01c169750506080830151915060a083015190506127da8282612a68565b9550505050505092959891949750929550565b5f546001600160a01b03163314612816576040516282b42960e81b815260040160405180910390fd5b565b5f806128238361149f565b90506001600160a01b038116610927575090919050565b5f6001600160a01b038416612876575f805f8085875af190508061287157604051633d2cec6f60e21b815260040160405180910390fd5b6128cc565b60405163a9059cbb60e01b5f52836004528260245260205f60445f80895af13d15601f3d1160015f511416171691505f6060528060405250806128cc57604051633c9fd93960e21b815260040160405180910390fd5b50505050565b306001600160a01b037f00000000000000000000000044533fbb68214caa579e2df0d5981aab3505bb1f16148061296b57507f00000000000000000000000044533fbb68214caa579e2df0d5981aab3505bb1f6001600160a01b031661295f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b156128165760405163703e46dd60e11b815260040160405180910390fd5b6129916127ed565b50565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156129ee575060408051601f3d908101601f191682019092526129eb91810190613e37565b60015b612a1b57604051634c9c8ce360e01b81526001600160a01b03831660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114612a5e57604051632a87526960e21b815260048101829052602401612a12565b6111918383613098565b612a70613410565b80516001600160a01b03848116909152815161ffff60a095861c8116602092830152818401805193861690935291519390941c16919092015290565b306001600160a01b037f00000000000000000000000044533fbb68214caa579e2df0d5981aab3505bb1f16146128165760405163703e46dd60e11b815260040160405180910390fd5b6128166130ed565b60605f8267ffffffffffffffff811115612b1957612b19613656565b604051908082528060200260200182016040528015612b4c57816020015b6060815260200190600190039081612b375790505b509050365f5b84811015612c2457858582818110612b6c57612b6c613f35565b9050602002810190612b7e919061407f565b91505f80612b8f602085018561347d565b6001600160a01b0316612ba56020860186613f49565b604051612bb3929190613f8c565b5f604051808303815f865af19150503d805f8114612bec576040519150601f19603f3d011682016040523d82523d5f602084013e612bf1565b606091505b50915091508115611be85780858481518110612c0f57612c0f613f35565b60200260200101819052505050600101612b52565b5090949350505050565b60405163e985e9c560e01b81523060048201526001600160a01b0382811660248301525f919084169063e985e9c590604401602060405180830381865afa158015612c7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c9f9190613fe9565b9050806111915760405163a22cb46560e01b81526001600160a01b0383811660048301526001602483015284169063a22cb465906044015f604051808303815f87803b158015612ced575f80fd5b505af1158015612cff573d5f803e3d5ffd5b50505050505050565b805f03612d1457505050565b604051636eb1769f60e11b81523060048201526001600160a01b0383811660248301525f919085169063dd62ed3e90604401602060405180830381865afa158015612d61573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d859190613e37565b9050818110156128cc5760405163095ea7b360e01b81526001600160a01b0384811660048301525f19602483015285169063095ea7b3906044016020604051808303815f875af1158015612ddb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118919190613fe9565b80515f5b81811015612e3857612e30868686868581518110612e2357612e23613f35565b602002602001015161313b565b600101612e03565b505050505050565b5f7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316836001600160a01b0316148015612e86575081608001514710155b15612fa5576080820151604051631e51809360e31b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169163f28c049891612edc908690600401614055565b60206040518083038185885af1158015612ef8573d5f803e3d5ffd5b50505050506040513d601f19601f82011682018060405250810190612f1d9190613e37565b90507f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b03166312210e8a6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612f77575f80fd5b505af1158015612f89573d5f803e3d5ffd5b505050505f471115612fa057612fa05f854761283a565b611498565b612fd4837f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615648460800151612d08565b612fe48385308560800151613196565b604051631e51809360e31b81526001600160a01b037f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564169063f28c049890613030908590600401614055565b6020604051808303815f875af115801561304c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130709190613e37565b905080826080015111156114985761149883858385608001516130939190613f22565b61283a565b6130a1826131f1565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156130e5576111918282613274565b6111b16132e6565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661281657604051631afcd79f60e31b815260040160405180910390fd5b5f604051632142170760e11b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f60605280604052508061189157604051636ff8a60f60e11b815260040160405180910390fd5b5f6040516323b872dd60e01b5f5284600452836024528260445260205f60645f808a5af13d15601f3d1160015f511416171691505f60605280604052508061189157604051633c9fd93960e21b815260040160405180910390fd5b806001600160a01b03163b5f0361322657604051634c9c8ce360e01b81526001600160a01b0382166004820152602401612a12565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b031684604051613290919061409d565b5f60405180830381855af49150503d805f81146132c8576040519150601f19603f3d011682016040523d82523d5f602084013e6132cd565b606091505b50915091506132dd858383613305565b95945050505050565b34156128165760405163b398979f60e01b815260040160405180910390fd5b60608261331557612fa08261335c565b815115801561332c57506001600160a01b0384163b155b1561335557604051639996b31560e01b81526001600160a01b0385166004820152602401612a12565b5080611498565b80511561336c5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6040805160e081019091525f606082018181526080830182905260a0830182905260c0830191909152819081526040805160a0810182525f80825260208281018290529282018190526060820181905260808201529101905b815260200161340b60405180604001604052805f6001600160a01b031681526020015f61ffff1681525090565b905290565b604080516080810182525f91810182815260608201929092529081906133de565b80356001600160a01b0381168114613447575f80fd5b919050565b5f806040838503121561345d575f80fd5b61346683613431565b915061347460208401613431565b90509250929050565b5f6020828403121561348d575f80fd5b61149882613431565b5f805f805f608086880312156134aa575f80fd5b6134b386613431565b94506134c160208701613431565b935060408601359250606086013567ffffffffffffffff808211156134e4575f80fd5b818801915088601f8301126134f7575f80fd5b813581811115613505575f80fd5b896020828501011115613516575f80fd5b9699959850939650602001949392505050565b5f805f6060848603121561353b575f80fd5b61354484613431565b925061355260208501613431565b9150604084013590509250925092565b815180516001600160a01b03908116835260208083015161ffff9081168286015260408085015182168187015260609485015182168587015282870151805190941660808088019190915292840151821660a087015283810151821660c087015293830151811660e08601529101511661010083015282015161016082019061360661012084018280516001600160a01b0316825260209081015161ffff16910152565b5092915050565b5f806040838503121561361e575f80fd5b61362783613431565b946020939093013593505050565b5f8060408385031215613646575f80fd5b8235915061347460208401613431565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561369357613693613656565b604052919050565b5f67ffffffffffffffff8211156136b4576136b4613656565b50601f01601f191660200190565b5f82601f8301126136d1575f80fd5b81356136e46136df8261369b565b61366a565b8181528460208386010111156136f8575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8060408385031215613725575f80fd5b61372e83613431565b9150602083013567ffffffffffffffff811115613749575f80fd5b613755858286016136c2565b9150509250929050565b61378182825180516001600160a01b0316825260209081015161ffff16910152565b60209081015180516001600160a01b03166040840152015161ffff16606090910152565b65ffffffffffff8c811682528b811660208301526001600160a01b038b811660408401526001600160601b038b811660608501528a16608084015267ffffffffffffffff891660a0840152871660c0830152851660e082015283151561010082015261012081018390526101c0810161382261014083018461375f565b9c9b505050505050505050505050565b6001600160601b038a1681526001600160a01b0389811660208301526fffffffffffffffffffffffffffffffff8981166040840152881660608301528681166080830152851660a082015267ffffffffffffffff841660c08201526101808101600384106138ae57634e487b7160e01b5f52602160045260245ffd5b8360e08301526138c261010083018461375f565b9a9950505050505050505050565b5f8083601f8401126138e0575f80fd5b50813567ffffffffffffffff8111156138f7575f80fd5b6020830191508360208260051b8501011115613911575f80fd5b9250929050565b5f60a08284031215613928575f80fd5b60405160a0810167ffffffffffffffff828210818311171561394c5761394c613656565b816040528293508435915080821115613963575f80fd5b50613970858286016136c2565b82525061397f60208401613431565b60208201526040830135604082015260608301356060820152608083013560808201525092915050565b5f805f805f805f60c0888a0312156139bf575f80fd5b6139c888613431565b9650602088013567ffffffffffffffff808211156139e4575f80fd5b6139f08b838c016138d0565b909850965060408a0135955060608a01359450869150613a1260808b01613431565b935060a08a0135915080821115613a27575f80fd5b50613a348a828b01613918565b91505092959891949750929550565b5f805f60608486031215613a55575f80fd5b613a5e84613431565b95602085013595506040909401359392505050565b5f8151808452602080850194508084015f5b83811015613aa157815187529582019590820190600101613a85565b509495945050505050565b602081525f6114986020830184613a73565b5f8060208385031215613acf575f80fd5b823567ffffffffffffffff811115613ae5575f80fd5b613af1858286016138d0565b90969095509350505050565b5f5b83811015613b17578181015183820152602001613aff565b50505f910152565b5f8151808452613b36816020860160208601613afd565b601f01601f19169290920160200192915050565b5f602080830181845280855180835260408601915060408160051b87010192508387015f5b82811015613b9d57603f19888603018452613b8b858351613b1f565b94509285019290850190600101613b6f565b5092979650505050505050565b602081525f6114986020830184613b1f565b8015158114612991575f80fd5b5f805f805f60808688031215613bdd575f80fd5b613be686613431565b9450602086013567ffffffffffffffff80821115613c02575f80fd5b613c0e89838a016138d0565b909650945060408801359150613c2382613bbc565b90925060608701359080821115613c38575f80fd5b50613c4588828901613918565b9150509295509295909350565b5f805f8060808587031215613c65575f80fd5b613c6e85613431565b966020860135965060408601359560600135945092505050565b602080825282518282018190525f919060409081850190868401855b82811015613ce857815180516001600160a01b031685528681015165ffffffffffff9081168887015290860151168585015260609093019290850190600101613ca4565b5091979650505050505050565b5f805f805f60a08688031215613d09575f80fd5b613d1286613431565b94506020860135935060408601359250613d2e60608701613431565b9150608086013567ffffffffffffffff811115613d49575f80fd5b613c4588828901613918565b8781526001600160a01b038716602082015260ff8616604082015260e060608201525f613d8560e0830187613a73565b60808301959095525063ffffffff9290921660a083015261ffff1660c090910152949350505050565b6001600160601b0388811682526001600160a01b038881166020840152908716604083015285811660608301528416608082015267ffffffffffffffff831660a08201526101408101613e0460c083018461375f565b98975050505050505050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561092757610927613e10565b5f60208284031215613e47575f80fd5b5051919050565b5f60208284031215613e5e575f80fd5b815167ffffffffffffffff811115613e74575f80fd5b8201601f81018413613e84575f80fd5b8051613e926136df8261369b565b818152856020838501011115613ea6575f80fd5b6132dd826020830160208601613afd565b8183525f7f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115613ee7575f80fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0384168152604060208201525f6132dd604083018486613eb7565b8181038181111561092757610927613e10565b634e487b7160e01b5f52603260045260245ffd5b5f808335601e19843603018112613f5e575f80fd5b83018035915067ffffffffffffffff821115613f78575f80fd5b602001915036819003821315613911575f80fd5b818382375f9101908152919050565b808202811582820484141761092757610927613e10565b5f6001600160a01b03808716835260606020840152613fd5606084018688613eb7565b915080841660408401525095945050505050565b5f60208284031215613ff9575f80fd5b815161149881613bbc565b5f815160a0845261401860a0850182613b1f565b90506001600160a01b0360208401511660208501526040830151604085015260608301516060850152608083015160808501528091505092915050565b602081525f6114986020830184614004565b5f6001820161407857614078613e10565b5060010190565b5f8235603e19833603018112614093575f80fd5b9190910192915050565b5f8251614093818460208701613afd56fea164736f6c6343000814000a
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
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.