Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18692757 | 447 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
NFTMarketRouter
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 1337000 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
/* ・ * ★ ・ 。 ・ ゚☆ 。 * ★ ゚・。 * 。 * ☆ 。・゚*.。 ゚ *.。☆。★ ・ ` .-:::::-.` `-::---...``` `-:` .:+ssssoooo++//:.` .-/+shhhhhhhhhhhhhyyyssooo: .--::. .+ossso+/////++/:://-` .////+shhhhhhhhhhhhhhhhhhhhhy `-----::. `/+////+++///+++/:--:/+/- -////+shhhhhhhhhhhhhhhhhhhhhy `------:::-` `//-.``.-/+ooosso+:-.-/oso- -////+shhhhhhhhhhhhhhhhhhhhhy .--------:::-` :+:.` .-/osyyyyyyso++syhyo.-////+shhhhhhhhhhhhhhhhhhhhhy `-----------:::-. +o+:-.-:/oyhhhhhhdhhhhhdddy:-////+shhhhhhhhhhhhhhhhhhhhhy .------------::::-- `oys+/::/+shhhhhhhdddddddddy/-////+shhhhhhhhhhhhhhhhhhhhhy .--------------:::::-` +ys+////+yhhhhhhhddddddddhy:-////+yhhhhhhhhhhhhhhhhhhhhhy `----------------::::::-`.ss+/:::+oyhhhhhhhhhhhhhhho`-////+shhhhhhhhhhhhhhhhhhhhhy .------------------:::::::.-so//::/+osyyyhhhhhhhhhys` -////+shhhhhhhhhhhhhhhhhhhhhy `.-------------------::/:::::..+o+////+oosssyyyyyyys+` .////+shhhhhhhhhhhhhhhhhhhhhy .--------------------::/:::.` -+o++++++oooosssss/. `-//+shhhhhhhhhhhhhhhhhhhhyo .------- ``````.......--` `-/+ooooosso+/-` `./++++///:::--...``hhhhyo ````` * ・ 。 ・ ゚☆ 。 * ★ ゚・。 * 。 * ☆ 。・゚*.。 ゚ *.。☆。★ ・ * ゚。·*・。 ゚* ☆゚・。°*. ゚ ・ ゚*。・゚★。 ・ *゚。 * ・゚*。★・ ☆∴。 * ・ 。 */ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "./mixins/shared/TxDeadline.sol"; import "./mixins/shared/WorldsNftNode.sol"; import "./mixins/shared/NFTMarketNode.sol"; import "./mixins/shared/NFTDropMarketNode.sol"; import "./mixins/shared/NFTCollectionFactoryNode.sol"; import "./mixins/nftMarketRouter/NFTCreateAndListTimedEditionCollection.sol"; import "./mixins/nftMarketRouter/NFTCreateAndListLimitedEditionCollection.sol"; import { NFTMarketRouterCore } from "./mixins/nftMarketRouter/NFTMarketRouterCore.sol"; import { NFTMarketRouterCreateFixedPriceSale } from "./mixins/nftMarketRouter/NFTMarketRouterCreateFixedPriceSale.sol"; import { NFTMarketRouterList } from "./mixins/nftMarketRouter/NFTMarketRouterList.sol"; import { NFTMarketRouterWorldsNftUserRoles } from "./mixins/nftMarketRouter/NFTMarketRouterWorldsNftUserRoles.sol"; import { NFTMarketRouterDutchAuction } from "./mixins/nftMarketRouter/NFTMarketRouterDutchAuction.sol"; import "./mixins/nftMarketRouter/apis/NFTMarketRouterAPIs.sol"; import "./mixins/nftMarketRouter/apis/NFTDropMarketRouterAPIs.sol"; import "./mixins/nftMarketRouter/apis/NFTCollectionFactoryRouterAPIs.sol"; import "./mixins/nftMarketRouter/apis/WorldsNftRouterAPIs.sol"; /** * @title A contract which offers value-added APIs and routes requests to the NFTMarket's existing API. * @dev Features in this contract can be created with a clear separation of concerns from the NFTMarket contract. * It also provides the contract size space required for targeted APIs and to experiment with new features. * @author batu-inal & HardlyDifficult & reggieag */ contract NFTMarketRouter is TxDeadline, NFTMarketNode, NFTCollectionFactoryNode, NFTDropMarketNode, NFTMarketRouterCore, WorldsNftNode, NFTMarketRouterAPIs, NFTCollectionFactoryRouterAPIs, NFTDropMarketRouterAPIs, WorldsNftRouterAPIs, NFTMarketRouterList, NFTCreateAndListTimedEditionCollection, NFTCreateAndListLimitedEditionCollection, NFTMarketRouterWorldsNftUserRoles, NFTMarketRouterCreateFixedPriceSale, NFTMarketRouterDutchAuction { /** * @notice Initialize the template's immutable variables. * @param _nftMarket The address of the NFTMarket contract to which requests will be routed. * @param _nftDropMarket The address of the NFTDropMarket contract to which requests will be routed. * @param _nftCollectionFactory The address of the NFTCollectionFactory contract to which requests will be routed. * @param _worlds The address of the Worlds contract to which requests will be routed. */ constructor( address _nftMarket, address _nftDropMarket, address _nftCollectionFactory, address _worlds ) NFTMarketNode(_nftMarket) NFTDropMarketNode(_nftDropMarket) NFTCollectionFactoryNode(_nftCollectionFactory) WorldsNftNode(_worlds) {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```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 Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * 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 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../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 caller. * * 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 v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @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 OR Apache-2.0 pragma solidity ^0.8.18; /** * @notice Interface for functions the market uses in FETH. * @author batu-inal & HardlyDifficult */ interface IFethMarket { function depositFor(address account) external payable; function marketLockupFor(address account, uint256 amount) external payable returns (uint256 expiration); function marketWithdrawFrom(address from, uint256 amount) external; function marketWithdrawLocked(address account, uint256 expiration, uint256 amount) external; function marketUnlockFor(address account, uint256 expiration, uint256 amount) external; function marketChangeLockup( address unlockFrom, uint256 unlockExpiration, uint256 unlockAmount, address lockupFor, uint256 lockupAmount ) external payable returns (uint256 expiration); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../mixins/shared/MarketStructs.sol"; interface IMarketUtils { function getTransactionBreakdown( MarketTransactionOptions calldata options ) external view returns ( uint256 protocolFeeAmount, address payable[] memory creatorRecipients, uint256[] memory creatorShares, uint256 sellerRev, uint256 buyReferrerFee, uint256 sellerReferrerFee ); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @title Declares the type of the collection contract. * @dev This interface is declared as an ERC-165 interface. * @author reggieag */ interface INFTCollectionType { function getNFTCollectionType() external view returns (string memory collectionType); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../mixins/shared/MarketStructs.sol"; /** * @title Interface with NFTMarket getters which are used by the router. * @author HardlyDifficult */ interface INFTMarketGetters { function getBuyPrice(address nftContract, uint256 tokenId) external view returns (address seller, uint256 price); function getExhibitionIdForNft( address nftContract, uint256 tokenId ) external view returns (uint256 worldOrExhibitionId); function getSaleStartsAt(address nftContract, uint256 tokenId) external view returns (uint256 saleStartsAt); function getReserveAuction(uint256 auctionId) external view returns (ReserveAuction memory auction); function getReserveAuctionIdFor(address nftContract, uint256 tokenId) external view returns (uint256 auctionId); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @notice Interface for AdminRole which wraps the default admin role from * OpenZeppelin's AccessControl for easy integration. * @author batu-inal & HardlyDifficult */ interface IAdminRole { function isAdmin(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @notice Interface for OperatorRole which wraps a role from * OpenZeppelin's AccessControl for easy integration. * @author batu-inal & HardlyDifficult */ interface IOperatorRole { function isOperator(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../../libraries/AddressLibrary.sol"; /** * @title Interface for routing calls to the NFT Collection Factory to create drop collections. * @author reggieag */ interface INFTCollectionFactoryDrops { function createNFTDropCollection( string calldata name, string calldata symbol, string calldata baseURI, bool isRevealed, uint32 maxTokenId, address approvedMinter, uint96 nonce ) external returns (address collection); function createNFTDropCollectionWithPaymentFactory( string calldata name, string calldata symbol, string calldata baseURI, bool isRevealed, uint32 maxTokenId, address approvedMinter, uint96 nonce, CallWithoutValue calldata paymentAddressFactoryCall ) external returns (address collection); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../../libraries/AddressLibrary.sol"; /** * @title Interface for routing calls to the NFT Collection Factory to create limited edition collections. * @author gosseti */ interface INFTCollectionFactoryLimitedEditions { function createNFTLimitedEditionCollection( string calldata name, string calldata symbol, string calldata baseURI, uint32 maxTokenId, address approvedMinter, uint96 nonce ) external returns (address collection); function createNFTLimitedEditionCollectionWithPaymentFactory( string calldata name, string calldata symbol, string calldata baseURI, uint32 maxTokenId, address approvedMinter, uint96 nonce, CallWithoutValue calldata paymentAddressFactoryCall ) external returns (address collection); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../../libraries/AddressLibrary.sol"; /** * @title Interface for routing calls to the NFT Collection Factory to create timed edition collections. * @author HardlyDifficult */ interface INFTCollectionFactoryTimedEditions { function createNFTTimedEditionCollection( string calldata name, string calldata symbol, string calldata tokenURI, uint256 mintEndTime, address approvedMinter, uint96 nonce ) external returns (address collection); function createNFTTimedEditionCollectionWithPaymentFactory( string calldata name, string calldata symbol, string calldata tokenURI, uint256 mintEndTime, address approvedMinter, uint96 nonce, CallWithoutValue calldata paymentAddressFactoryCall ) external returns (address collection); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; interface INFTDropMarketDutchAuction { function createLinearDutchAuction( address nftContract, uint256 worldOrExhibitionId, uint256 maxPrice, uint256 minPrice, uint256 limitPerAccount, uint256 startTime, uint256 saleDuration ) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @title Interface for routing calls to the NFT Drop Market to create fixed price sales. * @author HardlyDifficult & reggieag */ interface INFTDropMarketFixedPriceSale { function createFixedPriceSaleV3( address nftContract, uint256 worldOrExhibitionId, uint256 price, uint256 limitPerAccount, uint256 generalAvailabilityStartTime, uint256 txDeadlineTime ) external; function createFixedPriceSaleWithEarlyAccessAllowlistV2( address nftContract, uint256 worldOrExhibitionId, uint256 price, uint256 limitPerAccount, uint256 generalAvailabilityStartTime, uint256 earlyAccessStartTime, bytes32 merkleRoot, string calldata merkleTreeUri, uint256 txDeadlineTime ) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @title Interface for routing calls to the NFT Market to set buy now prices. * @author HardlyDifficult */ interface INFTMarketBuyNow { function cancelBuyPrice(address nftContract, uint256 tokenId) external; function setBuyPriceV2(address nftContract, uint256 tokenId, uint256 worldOrExhibitionId, uint256 price) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @title Interface for routing calls to the NFT Market Exhibition * @author philbirt */ interface INFTMarketExhibitionForRouter { function updateExhibitionNft(address nftContract, uint256 tokenId, uint256 price) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @title Interface for routing calls to the NFT Market to create reserve auctions. * @author HardlyDifficult & reggieag */ interface INFTMarketReserveAuction { function cancelReserveAuction(uint256 auctionId) external; function createReserveAuctionV3( address nftContract, uint256 tokenId, uint256 worldOrExhibitionId, uint256 reservePrice, uint256 duration ) external returns (uint256 auctionId); function updateReserveAuctionV2(uint256 auctionId, uint256 worldOrExhibitionId, uint256 reservePrice) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; interface INFTMarketScheduling { function setSaleStartsAt(address nftContract, uint256 tokenId, uint256 saleStartsAt) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; interface IWorldsNftUserRoles { function revokeAllRolesForUser(uint256 worldId, address user) external; function setAdminRole(uint256 worldId, address user) external; function setEditorRole(uint256 worldId, address user) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; struct CallWithoutValue { address target; bytes callData; } error AddressLibrary_Proxy_Call_Did_Not_Return_A_Contract(address addressReturned); /** * @title A library for address helpers not already covered by the OZ library. * @author batu-inal & HardlyDifficult */ library AddressLibrary { using AddressUpgradeable for address; using AddressUpgradeable for address payable; /** * @notice Calls an external contract with arbitrary data and parse the return value into an address. * @param externalContract The address of the contract to call. * @param callData The data to send to the contract. * @return contractAddress The address of the contract returned by the call. */ function callAndReturnContractAddress( address externalContract, bytes calldata callData ) internal returns (address payable contractAddress) { bytes memory returnData = externalContract.functionCall(callData); contractAddress = abi.decode(returnData, (address)); if (!contractAddress.isContract()) { revert AddressLibrary_Proxy_Call_Did_Not_Return_A_Contract(contractAddress); } } function callAndReturnContractAddress( CallWithoutValue calldata call ) internal returns (address payable contractAddress) { contractAddress = callAndReturnContractAddress(call.target, call.callData); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; error RouteCallLibrary_Call_Failed_Without_Revert_Reason(); /** * @title A library for calling external contracts with an address appended to the calldata. * @author HardlyDifficult */ library RouteCallLibrary { /** * @notice Routes a call to the specified contract, appending the from address to the end of the calldata. * If the call reverts, this will revert the transaction and the original reason is bubbled up. * @param from The address to use as the msg sender when calling the contract. * @param to The contract address to call. * @param callData The call data to use when calling the contract, without the sender appended. */ function routeCallTo(address from, address to, bytes memory callData) internal returns (bytes memory returnData) { // Forward the call, with the packed from address appended, to the specified contract. bool success; (success, returnData) = tryRouteCallTo(from, to, callData); // If the call failed, bubble up the revert reason. if (!success) { revertWithError(returnData); } } /** * @notice Routes a call to the specified contract, appending the from address to the end of the calldata. * This will not revert even if the external call fails. * @param from The address to use as the msg sender when calling the contract. * @param to The contract address to call. * @param callData The call data to use when calling the contract, without the sender appended. * @dev Consumers should look for positive confirmation that if the transaction is not successful, the returned revert * reason is expected as an acceptable reason to ignore. Generically ignoring reverts will lead to out-of-gas errors * being ignored and result in unexpected behavior. */ function tryRouteCallTo( address from, address to, bytes memory callData ) internal returns (bool success, bytes memory returnData) { // Forward the call, with the packed from address appended, to the specified contract. // solhint-disable-next-line avoid-low-level-calls (success, returnData) = to.call(abi.encodePacked(callData, from)); } /** * @notice Bubbles up the original revert reason of a low-level call failure where possible. * @dev Copied from OZ's `Address.sol` library, with a minor modification to the final revert scenario. * This should only be used when a low-level call fails. */ function revertWithError(bytes memory returnData) internal 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 RouteCallLibrary_Call_Failed_Without_Revert_Reason(); } } /** * @notice Extracts the appended sender address from the calldata. * @dev This uses the last 20 bytes of the calldata, with no guarantees that an address has indeed been appended. * If this is used for a call that was not routed with `routeCallTo`, the address returned will be incorrect (and * may be address(0)). */ function extractAppendedSenderAddress() internal pure returns (address sender) { assembly { // The router appends the msg.sender to the end of the calldata // source: https://github.com/opengsn/gsn/blob/v3.0.0-beta.3/packages/contracts/src/ERC2771Recipient.sol#L48 sender := shr(96, calldataload(sub(calldatasize(), 20))) } } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @title Helpers for working with time. * @author batu-inal & HardlyDifficult */ library TimeLibrary { /** * @notice Checks if the given timestamp is in the past. * @dev This helper ensures a consistent interpretation of expiry across the codebase. * This is different than `hasBeenReached` in that it will return false if the expiry is now. */ function hasExpired(uint256 expiry) internal view returns (bool) { return expiry < block.timestamp; } /** * @notice Checks if the given timestamp is now or in the past. * @dev This helper ensures a consistent interpretation of expiry across the codebase. * This is different from `hasExpired` in that it will return true if the timestamp is now. */ function hasBeenReached(uint256 timestamp) internal view returns (bool) { return timestamp <= block.timestamp; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "../../interfaces/internal/IFethMarket.sol"; import "../shared/Constants.sol"; import "../shared/MarketSharedCore.sol"; error NFTMarketCore_Seller_Not_Found(); error NFTMarketCore_Can_Not_Update_Unlisted_Nft(); /** * @title A place for common modifiers and functions used by various NFTMarket mixins, if any. * @dev This also leaves a gap which can be used to add a new mixin to the top of the inheritance tree. * @author batu-inal & HardlyDifficult */ abstract contract NFTMarketCore is ContextUpgradeable, MarketSharedCore { using AddressUpgradeable for address; using AddressUpgradeable for address payable; /** * @notice If there is a buy price at this amount or lower, accept that and return true. */ function _autoAcceptBuyPrice(address nftContract, uint256 tokenId, uint256 amount) internal virtual returns (bool); /** * @notice If there is a valid offer at the given price or higher, accept that and return true. */ function _autoAcceptOffer(address nftContract, uint256 tokenId, uint256 minAmount) internal virtual returns (bool); /** * @notice Notify implementors when an auction has received its first bid. * Once a bid is received the sale is guaranteed to the auction winner * and other sale mechanisms become unavailable. * @dev Implementors of this interface should update internal state to reflect an auction has been kicked off. */ function _beforeAuctionStarted(address /*nftContract*/, uint256 /*tokenId*/) internal virtual { // No-op } /** * @notice Requires that an NFT is listed for sale, not in active auction, and the msg.sender is the seller which * listed the NFT. */ function _authorizeExhibitionOrScheduleUpdate(address nftContract, uint256 tokenId) internal view { if (!_isAuthorizedExhibitionOrScheduleUpdate(nftContract, tokenId)) { revert NFTMarketCore_Can_Not_Update_Unlisted_Nft(); } } /** * @notice Confirms permission to update the Exhibition or schedule for an NFT. * @return canUpdateNft True if the NFT is listed for sale and authorize checks did not revert. * @dev Verifies that the NFT is listed, not in active auction, and the sender is the owner. */ function _isAuthorizedExhibitionOrScheduleUpdate( address /*nftContract*/, uint256 /*tokenId*/ ) internal view virtual returns (bool canUpdateNft) { // False by default, may be set to true by a market tool mixin if the NFT is listed. } /** * @notice Cancel the `msg.sender`'s offer if there is one, freeing up their FETH balance. * @dev This should be used when it does not make sense to keep the original offer around, * e.g. if a collector accepts a Buy Price then keeping the offer around is not necessary. */ function _cancelSendersOffer(address nftContract, uint256 tokenId) internal virtual; /** * @notice Transfers the NFT from escrow and clears any state tracking this escrowed NFT. * @param authorizeSeller The address of the seller pending authorization. * Once it's been authorized by one of the escrow managers, it should be set to address(0) * indicated that it's no longer pending authorization. */ function _transferFromEscrow( address nftContract, uint256 tokenId, address recipient, address authorizeSeller ) internal virtual { if (authorizeSeller != address(0)) { revert NFTMarketCore_Seller_Not_Found(); } IERC721(nftContract).transferFrom(address(this), recipient, tokenId); } /** * @notice Transfers the NFT from escrow unless there is another reason for it to remain in escrow. */ function _transferFromEscrowIfAvailable( address nftContract, uint256 tokenId, address originalSeller ) internal virtual { _transferFromEscrow(nftContract, tokenId, originalSeller, address(0)); } /** * @notice Transfers an NFT into escrow, * if already there this requires the msg.sender is authorized to manage the sale of this NFT. */ function _transferToEscrow(address nftContract, uint256 tokenId) internal virtual { IERC721(nftContract).transferFrom(_msgSender(), address(this), tokenId); } /** * @dev Determines the minimum amount when increasing an existing offer or bid. */ function _getMinIncrement(uint256 currentAmount) internal pure returns (uint256) { uint256 minIncrement = currentAmount; unchecked { minIncrement /= MIN_PERCENT_INCREMENT_DENOMINATOR; } if (minIncrement == 0) { // Since minIncrement reduces from the currentAmount, this cannot overflow. // The next amount must be at least 1 wei greater than the current. return currentAmount + 1; } return minIncrement + currentAmount; } /** * @inheritdoc MarketSharedCore */ function _getSellerOrOwnerOf( address nftContract, uint256 tokenId ) internal view override returns (address payable sellerOrOwner) { sellerOrOwner = _getSellerOf(nftContract, tokenId); if (sellerOrOwner == address(0)) { sellerOrOwner = payable(IERC721(nftContract).ownerOf(tokenId)); } } /** * @notice Checks if an escrowed NFT is currently in active auction. * @return Returns false if the auction has ended, even if it has not yet been settled. */ function _isInActiveAuction(address nftContract, uint256 tokenId) internal view virtual returns (bool); /** * @notice This empty reserved space is put in place to allow future versions to add new variables without shifting * down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps * @dev 50 slots were consumed by adding `ReentrancyGuard`. */ uint256[450] private __gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "../../libraries/TimeLibrary.sol"; import "../../interfaces/internal/routes/INFTMarketScheduling.sol"; import "../../interfaces/internal/INFTMarketGetters.sol"; import "../shared/Constants.sol"; import "../shared/MarketFees.sol"; import "./NFTMarketCore.sol"; // Errors when configuring a schedule error NFTMarketScheduling_Sale_Starts_At_Already_Set(); error NFTMarketScheduling_Sale_Starts_At_Is_In_Past(); error NFTMarketScheduling_Sale_Starts_At_Too_Far_In_The_Future(uint256 maxStartsAt); // Errors when validating a schedule error NFTMarketScheduling_Sale_Starts_At_Is_In_Future(); /** * @title Allows listed NFTs to schedule a sale starts at time. * @dev This supports both Auctions and BuyNow. * @author HardlyDifficult & smhutch */ abstract contract NFTMarketScheduling is INFTMarketGetters, INFTMarketScheduling, ContextUpgradeable, NFTMarketCore, MarketFees { using TimeLibrary for uint256; /// @notice Stores the saleStartsAt time for listed NFTs mapping(address => mapping(uint256 => uint256)) private $nftContractToTokenIdToSaleStartsAt; /** * @notice emitted when an a saleStartsAt time is changed for an NFT. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT. * @param operator The address that triggered this change. * @param saleStartsAt The time at which the NFT will be available to buy or place bids on. * When zero, this represents that the NFT is unscheduled. * When above zero, this value represents the time in seconds since the Unix epoch. */ event SetSaleStartsAt( address indexed nftContract, uint256 indexed tokenId, address indexed operator, uint256 saleStartsAt ); //////////////////////////////////////////////////////////////// // Configuration //////////////////////////////////////////////////////////////// /** * @notice sets the saleStartsAt time for a listed NFT. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT. * @param saleStartsAt The time at which the NFT will be available to buy or place bids on. * When zero, the NFT has no saleStartsAt and can be purchased anytime. * When above zero, this value represents the time in seconds since the Unix epoch. */ function setSaleStartsAt(address nftContract, uint256 tokenId, uint256 saleStartsAt) external { // Check if it's already set first since this may be a common occurrence. if ($nftContractToTokenIdToSaleStartsAt[nftContract][tokenId] == saleStartsAt) { revert NFTMarketScheduling_Sale_Starts_At_Already_Set(); } _authorizeExhibitionOrScheduleUpdate(nftContract, tokenId); if (saleStartsAt != 0) { if (saleStartsAt.hasExpired()) { revert NFTMarketScheduling_Sale_Starts_At_Is_In_Past(); } if (saleStartsAt > block.timestamp + MAX_SCHEDULED_TIME_IN_THE_FUTURE) { // Prevent arbitrarily large values from accidentally being set. revert NFTMarketScheduling_Sale_Starts_At_Too_Far_In_The_Future( block.timestamp + MAX_SCHEDULED_TIME_IN_THE_FUTURE ); } } $nftContractToTokenIdToSaleStartsAt[nftContract][tokenId] = saleStartsAt; emit SetSaleStartsAt({ nftContract: nftContract, tokenId: tokenId, operator: _msgSender(), saleStartsAt: saleStartsAt }); } /** * @notice Returns the saleStartsAt time for a listed NFT. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT. * @return saleStartsAt The time at which the NFT will be available to buy or place bids on. * 0 if there is no schedule set and the NFT may be purchased anytime (or is not yet listed). */ function getSaleStartsAt(address nftContract, uint256 tokenId) external view returns (uint256 saleStartsAt) { saleStartsAt = $nftContractToTokenIdToSaleStartsAt[nftContract][tokenId]; } //////////////////////////////////////////////////////////////// // Validation //////////////////////////////////////////////////////////////// function _validateSaleStartsAtHasBeenReached(address nftContract, uint256 tokenId) internal view { if (!$nftContractToTokenIdToSaleStartsAt[nftContract][tokenId].hasBeenReached()) { revert NFTMarketScheduling_Sale_Starts_At_Is_In_Future(); } } /** * @inheritdoc NFTMarketCore * @dev Validates the saleStartsAt time for the NFT when the first bid is placed. */ function _beforeAuctionStarted(address nftContract, uint256 tokenId) internal virtual override { _validateSaleStartsAtHasBeenReached(nftContract, tokenId); super._beforeAuctionStarted(nftContract, tokenId); } //////////////////////////////////////////////////////////////// // Cleanup //////////////////////////////////////////////////////////////// function _clearScheduleIfSet(address nftContract, uint256 tokenId) private { if ($nftContractToTokenIdToSaleStartsAt[nftContract][tokenId] != 0) { // Clear the saleStartsAt time so that it does not apply to the next listing delete $nftContractToTokenIdToSaleStartsAt[nftContract][tokenId]; emit SetSaleStartsAt({ nftContract: nftContract, tokenId: tokenId, operator: _msgSender(), saleStartsAt: 0 }); } } /** * @dev When a sale occurs, clear the schedule if one was set. */ function _distributeFunds( address nftContract, uint256 tokenId, address payable seller, uint256 price, address payable buyReferrer, address payable sellerReferrerPaymentAddress, uint16 sellerReferrerTakeRateInBasisPoints ) internal virtual override returns (uint256 totalFees, uint256 creatorRev, uint256 sellerRev) { _clearScheduleIfSet(nftContract, tokenId); (totalFees, creatorRev, sellerRev) = super._distributeFunds( nftContract, tokenId, seller, price, buyReferrer, sellerReferrerPaymentAddress, sellerReferrerTakeRateInBasisPoints ); } /** * @dev Called when a listing is canceled. This mixin appears before the market tools in inheritance order, so when * this is called we have already confirmed that the NFT is no longer listed and will indeed leave escrow. */ function _transferFromEscrowIfAvailable( address nftContract, uint256 tokenId, address originalSeller ) internal virtual override { _clearScheduleIfSet(nftContract, tokenId); super._transferFromEscrowIfAvailable(nftContract, tokenId, originalSeller); } /** * @notice This empty reserved space is put in place to allow future versions to add new variables without shifting * down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps * @dev This mixin uses 250 slots in total. */ uint256[249] private __gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../../interfaces/internal/routes/INFTCollectionFactoryDrops.sol"; import "../../../interfaces/internal/routes/INFTCollectionFactoryTimedEditions.sol"; import "../../../interfaces/internal/routes/INFTDropMarketFixedPriceSale.sol"; import "../../../interfaces/internal/routes/INFTCollectionFactoryLimitedEditions.sol"; import "../../../libraries/AddressLibrary.sol"; import "../../../libraries/RouteCallLibrary.sol"; import "../../shared/NFTDropMarketNode.sol"; import "../../shared/NFTCollectionFactoryNode.sol"; /// @notice Parameters used to create a drop collection. struct DropCollectionCreationParams { /// @notice The collection's `name`. string name; /// @notice The collection's `symbol`. string symbol; /// @notice The base URI for the collection. string baseURI; /// @notice Whether the collection is revealed or not. bool isRevealed; /// @notice The max `tokenID` for this collection. uint32 maxTokenId; /// @notice The nonce used by the creator to create this collection. uint96 nonce; } /// @notice Parameters used to create a limited edition collection. struct LimitedEditionCollectionCreationParams { /// @notice The collection's `name`. string name; /// @notice The collection's `symbol`. string symbol; /// @notice The token URI for the collection. string tokenURI; /// @notice The max `tokenID` for this collection. uint32 maxTokenId; /// @notice The nonce used by the creator to create this collection. uint96 nonce; } /// @notice Parameters used to create a timed edition collection. struct TimedEditionCollectionCreationParams { /// @notice The collection's `name`. string name; /// @notice The collection's `symbol`. string symbol; /// @notice The token URI for the collection. string tokenURI; /// @notice The nonce used by the creator to create this collection. uint96 nonce; } /** * @title Wraps external calls to the NFTCollectionFactory contract. * @dev Each call uses standard APIs and params, along with the msg.sender appended to the calldata. They will decode * return values as appropriate. If any of these calls fail, the tx will revert with the original reason. * @author HardlyDifficult & reggieag */ abstract contract NFTCollectionFactoryRouterAPIs is NFTCollectionFactoryNode, NFTDropMarketNode { using RouteCallLibrary for address; function _createNFTDropCollection( DropCollectionCreationParams calldata collectionParams ) internal returns (address collection) { bytes memory returnData = msg.sender.routeCallTo( nftCollectionFactory, abi.encodeCall( INFTCollectionFactoryDrops.createNFTDropCollection, ( collectionParams.name, collectionParams.symbol, collectionParams.baseURI, collectionParams.isRevealed, collectionParams.maxTokenId, nftDropMarket, collectionParams.nonce ) ) ); collection = abi.decode(returnData, (address)); } function _createNFTDropCollectionWithPaymentFactory( DropCollectionCreationParams calldata collectionParams, CallWithoutValue calldata paymentAddressFactoryCall ) internal returns (address collection) { bytes memory returnData = msg.sender.routeCallTo( nftCollectionFactory, abi.encodeCall( INFTCollectionFactoryDrops.createNFTDropCollectionWithPaymentFactory, ( collectionParams.name, collectionParams.symbol, collectionParams.baseURI, collectionParams.isRevealed, collectionParams.maxTokenId, nftDropMarket, collectionParams.nonce, paymentAddressFactoryCall ) ) ); collection = abi.decode(returnData, (address)); } function _createNFTTimedEditionCollection( string calldata name, string calldata symbol, string calldata tokenURI, uint256 mintEndTime, address approvedMinter, uint96 nonce ) internal returns (address collection) { bytes memory returnData = msg.sender.routeCallTo( nftCollectionFactory, abi.encodeCall( INFTCollectionFactoryTimedEditions.createNFTTimedEditionCollection, (name, symbol, tokenURI, mintEndTime, approvedMinter, nonce) ) ); collection = abi.decode(returnData, (address)); } function _createNFTTimedEditionCollectionWithPaymentFactory( string calldata name, string calldata symbol, string calldata tokenURI, uint256 mintEndTime, address approvedMinter, uint96 nonce, CallWithoutValue calldata paymentAddressFactoryCall ) internal returns (address collection) { bytes memory returnData = msg.sender.routeCallTo( nftCollectionFactory, abi.encodeCall( INFTCollectionFactoryTimedEditions.createNFTTimedEditionCollectionWithPaymentFactory, (name, symbol, tokenURI, mintEndTime, approvedMinter, nonce, paymentAddressFactoryCall) ) ); collection = abi.decode(returnData, (address)); } function _createNFTLimitedEditionCollection( LimitedEditionCollectionCreationParams calldata collectionParams ) internal returns (address collection) { bytes memory returnData = msg.sender.routeCallTo( nftCollectionFactory, abi.encodeCall( INFTCollectionFactoryLimitedEditions.createNFTLimitedEditionCollection, ( collectionParams.name, collectionParams.symbol, collectionParams.tokenURI, collectionParams.maxTokenId, nftDropMarket, collectionParams.nonce ) ) ); collection = abi.decode(returnData, (address)); } function _createNFTLimitedEditionCollectionWithPaymentFactory( LimitedEditionCollectionCreationParams calldata collectionParams, CallWithoutValue calldata paymentAddressFactoryCall ) internal returns (address collection) { bytes memory returnData = msg.sender.routeCallTo( nftCollectionFactory, abi.encodeCall( INFTCollectionFactoryLimitedEditions.createNFTLimitedEditionCollectionWithPaymentFactory, ( collectionParams.name, collectionParams.symbol, collectionParams.tokenURI, collectionParams.maxTokenId, nftDropMarket, collectionParams.nonce, paymentAddressFactoryCall ) ) ); collection = abi.decode(returnData, (address)); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../../interfaces/internal/routes/INFTDropMarketFixedPriceSale.sol"; import { INFTDropMarketDutchAuction } from "../../../interfaces/internal/routes/INFTDropMarketDutchAuction.sol"; import "../../../libraries/RouteCallLibrary.sol"; import "../../shared/NFTDropMarketNode.sol"; /// @notice Parameters used to create a fixed price sale. struct FixedPriceSaleParams { /// @notice The World NFT or exhibition ID to associate this fix priced sale to. /// Set this to 0 to exist outside of a World/exhibition. uint256 worldOrExhibitionId; /// @notice The fixed price per NFT in the collection. uint256 price; /// @notice The max number of NFTs an account may mint in this sale. uint256 limitPerAccount; /// @notice The start time of the general availability period, in seconds since the Unix epoch. /// @dev When set to 0, general availability is set to the block timestamp the transaction is mined. uint256 generalAvailabilityStartTime; } /// @notice Parameters used to create a fixed price sale. struct FixedPriceSaleParamsV2 { /// @notice The World NFT or exhibition ID to associate this fix priced sale to. /// Set this to 0 to exist outside of a World/exhibition. uint256 worldOrExhibitionId; /// @notice The fixed price per NFT in the collection. uint256 price; /// @notice The max number of NFTs an account may mint in this sale. uint256 limitPerAccount; /// @notice The start time of the general availability period, in seconds since the Unix epoch. /// @dev When set to 0, general availability is set to the block timestamp the transaction is mined. uint256 generalAvailabilityStartTime; /// @notice The sale duration in seconds. uint256 saleDuration; } /** * @title Wraps external calls to the NFTDropMarket contract. * @dev Each call uses standard APIs and params, along with the msg.sender appended to the calldata. They will decode * return values as appropriate. If any of these calls fail, the tx will revert with the original reason. * @author HardlyDifficult & reggieag */ abstract contract NFTDropMarketRouterAPIs is NFTDropMarketNode { using RouteCallLibrary for address; function _createFixedPriceSaleV3( address nftContract, FixedPriceSaleParams memory fixedPriceSaleParams, uint256 txDeadlineTime ) internal { msg.sender.routeCallTo( nftDropMarket, abi.encodeCall( INFTDropMarketFixedPriceSale.createFixedPriceSaleV3, ( nftContract, fixedPriceSaleParams.worldOrExhibitionId, fixedPriceSaleParams.price, fixedPriceSaleParams.limitPerAccount, fixedPriceSaleParams.generalAvailabilityStartTime, txDeadlineTime ) ) ); } function _createFixedPriceSaleWithEarlyAccessAllowlistV2( address nftContract, FixedPriceSaleParams memory fixedPriceSaleParams, uint256 earlyAccessStartTime, bytes32 merkleRoot, string calldata merkleTreeUri, uint256 txDeadlineTime ) internal { msg.sender.routeCallTo( nftDropMarket, abi.encodeCall( INFTDropMarketFixedPriceSale.createFixedPriceSaleWithEarlyAccessAllowlistV2, ( nftContract, fixedPriceSaleParams.worldOrExhibitionId, fixedPriceSaleParams.price, fixedPriceSaleParams.limitPerAccount, fixedPriceSaleParams.generalAvailabilityStartTime, earlyAccessStartTime, merkleRoot, merkleTreeUri, txDeadlineTime ) ) ); } function _createLinearDutchAuction( address nftContract, uint256 worldOrExhibitionId, uint256 maxPrice, uint256 minPrice, uint256 limitPerAccount, uint256 startTime, uint256 saleDuration ) internal { msg.sender.routeCallTo( nftDropMarket, abi.encodeCall( INFTDropMarketDutchAuction.createLinearDutchAuction, (nftContract, worldOrExhibitionId, maxPrice, minPrice, limitPerAccount, startTime, saleDuration) ) ); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../../interfaces/internal/routes/INFTMarketBuyNow.sol"; import "../../../interfaces/internal/routes/INFTMarketExhibition.sol"; import "../../../interfaces/internal/routes/INFTMarketReserveAuction.sol"; import "../../../interfaces/internal/routes/INFTMarketScheduling.sol"; import "../../../libraries/RouteCallLibrary.sol"; import { NFTMarketScheduling_Sale_Starts_At_Already_Set } from "../../nftMarket/NFTMarketScheduling.sol"; import "../../shared/NFTMarketNode.sol"; /** * @title Wraps external calls to the NFTMarket contract. * @dev Each call uses standard APIs and params, along with the msg.sender appended to the calldata. They will decode * return values as appropriate. If any of these calls fail, the tx will revert with the original reason. * @author HardlyDifficult, reggieag */ abstract contract NFTMarketRouterAPIs is NFTMarketNode { using RouteCallLibrary for address; //////////////////////////////////////////////////////////////// // Auctions //////////////////////////////////////////////////////////////// function _cancelReserveAuction(uint256 auctionId) internal { msg.sender.routeCallTo(nftMarket, abi.encodeCall(INFTMarketReserveAuction.cancelReserveAuction, (auctionId))); } function _createReserveAuctionV3( address nftContract, uint256 tokenId, uint256 worldOrExhibitionId, uint256 reservePrice, uint256 duration ) internal returns (uint256 auctionId) { bytes memory returnData = msg.sender.routeCallTo( nftMarket, abi.encodeCall( INFTMarketReserveAuction.createReserveAuctionV3, (nftContract, tokenId, worldOrExhibitionId, reservePrice, duration) ) ); auctionId = abi.decode(returnData, (uint256)); } function _updateReserveAuctionV2(uint256 auctionId, uint256 worldOrExhibitionId, uint256 reservePrice) internal { msg.sender.routeCallTo( nftMarket, abi.encodeCall(INFTMarketReserveAuction.updateReserveAuctionV2, (auctionId, worldOrExhibitionId, reservePrice)) ); } //////////////////////////////////////////////////////////////// // Buy Now //////////////////////////////////////////////////////////////// function _cancelBuyPrice(address nftContract, uint256 tokenId) internal { msg.sender.routeCallTo(nftMarket, abi.encodeCall(INFTMarketBuyNow.cancelBuyPrice, (nftContract, tokenId))); } function _setBuyPriceV2(address nftContract, uint256 tokenId, uint256 worldOrExhibitionId, uint256 price) internal { msg.sender.routeCallTo( nftMarket, abi.encodeCall(INFTMarketBuyNow.setBuyPriceV2, (nftContract, tokenId, worldOrExhibitionId, price)) ); } //////////////////////////////////////////////////////////////// // Exhibitions //////////////////////////////////////////////////////////////// function _updateNftExhibition(address nftContract, uint256 tokenId, uint256 worldOrExhibitionId) internal { msg.sender.routeCallTo( nftMarket, abi.encodeCall(INFTMarketExhibitionForRouter.updateExhibitionNft, (nftContract, tokenId, worldOrExhibitionId)) ); } //////////////////////////////////////////////////////////////// // Scheduling //////////////////////////////////////////////////////////////// function _setSaleStartsAt(address nftContract, uint256 tokenId, uint256 saleStartsAt) internal { msg.sender.routeCallTo( nftMarket, abi.encodeCall(INFTMarketScheduling.setSaleStartsAt, (nftContract, tokenId, saleStartsAt)) ); } function _setSaleStartsAtAndIgnoreErrorIfStartsAtAlreadySet( address nftContract, uint256 tokenId, uint256 saleStartsAt ) internal { (bool success, bytes memory returnData) = msg.sender.tryRouteCallTo( nftMarket, abi.encodeCall(INFTMarketScheduling.setSaleStartsAt, (nftContract, tokenId, saleStartsAt)) ); if (!success && bytes4(returnData) != NFTMarketScheduling_Sale_Starts_At_Already_Set.selector) { RouteCallLibrary.revertWithError(returnData); } } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../../interfaces/internal/routes/IWorldsNftUserRoles.sol"; import "../../../libraries/RouteCallLibrary.sol"; import "../../shared/WorldsNftNode.sol"; abstract contract WorldsNftRouterAPIs is WorldsNftNode { using RouteCallLibrary for address; function _revokeAllRolesForUser(uint256 worldId, address user) internal { msg.sender.routeCallTo(worlds, abi.encodeCall(IWorldsNftUserRoles.revokeAllRolesForUser, (worldId, user))); } function _setAdminRole(uint256 worldId, address user) internal { msg.sender.routeCallTo(worlds, abi.encodeCall(IWorldsNftUserRoles.setAdminRole, (worldId, user))); } function _setEditorRole(uint256 worldId, address user) internal { msg.sender.routeCallTo(worlds, abi.encodeCall(IWorldsNftUserRoles.setEditorRole, (worldId, user))); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../libraries/AddressLibrary.sol"; import "../shared/TxDeadline.sol"; import "./apis/NFTCollectionFactoryRouterAPIs.sol"; import "./apis/NFTDropMarketRouterAPIs.sol"; /** * @title Offers value-added functions for creating limited edition collections using the NFTCollectionFactory contract * and creating sales using the NFTDropMarket contract. * An example of a value-added function is the ability to create a collection and sale in a single transaction. * @author gosseti */ abstract contract NFTCreateAndListLimitedEditionCollection is TxDeadline, NFTCollectionFactoryRouterAPIs, NFTDropMarketRouterAPIs { /** * @notice Create a new limited edition collection contract and fixed price sale. * @param collectionParams The parameters for the limited edition collection creation. * @param fixedPriceSaleParams The parameters for the fixed price sale creation. * @param txDeadlineTime The deadline timestamp for the transaction to be mined, in seconds since Unix epoch. * @return collection The address of the newly created collection contract. * @dev The collection will include the `nftDropMarket` as an approved minter. */ function createLimitedEditionCollectionAndFixedPriceSale( LimitedEditionCollectionCreationParams calldata collectionParams, FixedPriceSaleParams calldata fixedPriceSaleParams, uint256 txDeadlineTime ) external txDeadlineNotExpired(txDeadlineTime) returns (address collection) { collection = _createNFTLimitedEditionCollection({ collectionParams: collectionParams }); _createFixedPriceSaleV3({ nftContract: collection, fixedPriceSaleParams: fixedPriceSaleParams, // The deadline provided has already been validated above. txDeadlineTime: 0 }); } /** * @notice Create a new limited edition collection contract with a payment factory and fixed price sale. * @param collectionParams The parameters for the limited edition collection creation. * @param paymentAddressFactoryCall The contract call which will return the address to use for payments. * @param fixedPriceSaleParams The parameters for the fixed price sale creation. * @param txDeadlineTime The deadline timestamp for the transaction to be mined, in seconds since Unix epoch. * @return collection The address of the newly created collection contract. * @dev The collection will include the `nftDropMarket` as an approved minter. */ function createLimitedEditionCollectionAndFixedPriceSaleWithPaymentFactory( LimitedEditionCollectionCreationParams calldata collectionParams, CallWithoutValue calldata paymentAddressFactoryCall, FixedPriceSaleParams calldata fixedPriceSaleParams, uint256 txDeadlineTime ) external txDeadlineNotExpired(txDeadlineTime) returns (address collection) { collection = _createNFTLimitedEditionCollectionWithPaymentFactory({ collectionParams: collectionParams, paymentAddressFactoryCall: paymentAddressFactoryCall }); _createFixedPriceSaleV3({ nftContract: collection, fixedPriceSaleParams: fixedPriceSaleParams, // The deadline provided has already been validated above. txDeadlineTime: 0 }); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../libraries/AddressLibrary.sol"; import "../shared/TxDeadline.sol"; import "./apis/NFTCollectionFactoryRouterAPIs.sol"; import "./apis/NFTDropMarketRouterAPIs.sol"; error NFTCreateAndListTimedEditionCollection_Sale_Duration_Cannot_Be_Zero(); /** * @title Offers value-added functions for creating edition collections using the NFTCollectionFactory contract * and creating sales using the NFTDropMarket contract. * An example of a value-added function is the ability to create a collection and sale in a single transaction. * @author reggieag & HardlyDifficult & gosseti */ abstract contract NFTCreateAndListTimedEditionCollection is TxDeadline, NFTCollectionFactoryRouterAPIs, NFTDropMarketRouterAPIs { /** * @notice Create a new edition collection contract and timed sale. * @param collectionParams The parameters for the edition collection creation. * @param fixedPriceSaleParams The parameters for the sale creation. * @param txDeadlineTime The deadline timestamp for the transaction to be mined, in seconds since Unix epoch. * @return collection The address of the newly created collection contract. * @dev The collection will include the `nftDropMarket` as an approved minter. */ function createTimedEditionCollectionAndFixedPriceSaleV2( TimedEditionCollectionCreationParams calldata collectionParams, FixedPriceSaleParamsV2 calldata fixedPriceSaleParams, uint256 txDeadlineTime ) external txDeadlineNotExpired(txDeadlineTime) returns (address collection) { if (fixedPriceSaleParams.saleDuration == 0) { revert NFTCreateAndListTimedEditionCollection_Sale_Duration_Cannot_Be_Zero(); } uint256 generalAvailabilityStartTime = fixedPriceSaleParams.generalAvailabilityStartTime; if (generalAvailabilityStartTime == 0) { generalAvailabilityStartTime = block.timestamp; } collection = _createNFTTimedEditionCollection({ name: collectionParams.name, symbol: collectionParams.symbol, tokenURI: collectionParams.tokenURI, mintEndTime: generalAvailabilityStartTime + fixedPriceSaleParams.saleDuration, approvedMinter: nftDropMarket, nonce: collectionParams.nonce }); FixedPriceSaleParams memory mappedFixedPriceSaleParams = FixedPriceSaleParams({ worldOrExhibitionId: fixedPriceSaleParams.worldOrExhibitionId, price: fixedPriceSaleParams.price, limitPerAccount: fixedPriceSaleParams.limitPerAccount, generalAvailabilityStartTime: fixedPriceSaleParams.generalAvailabilityStartTime }); _createFixedPriceSaleV3({ nftContract: collection, fixedPriceSaleParams: mappedFixedPriceSaleParams, // The deadline provided has already been validated above. txDeadlineTime: 0 }); } /** * @notice Create a new edition collection contract and timed sale with a payment factory. * @param collectionParams The parameters for the edition collection creation. * @param paymentAddressFactoryCall The contract call which will return the address to use for payments. * @param fixedPriceSaleParams The parameters for the sale creation. * @param txDeadlineTime The deadline timestamp for the transaction to be mined, in seconds since Unix epoch. * @return collection The address of the newly created collection contract. * @dev The collection will include the `nftDropMarket` as an approved minter. */ function createTimedEditionCollectionAndFixedPriceSaleWithPaymentFactoryV2( TimedEditionCollectionCreationParams calldata collectionParams, CallWithoutValue calldata paymentAddressFactoryCall, FixedPriceSaleParamsV2 calldata fixedPriceSaleParams, uint256 txDeadlineTime ) external txDeadlineNotExpired(txDeadlineTime) returns (address collection) { if (fixedPriceSaleParams.saleDuration == 0) { revert NFTCreateAndListTimedEditionCollection_Sale_Duration_Cannot_Be_Zero(); } uint256 generalAvailabilityStartTime = fixedPriceSaleParams.generalAvailabilityStartTime; if (generalAvailabilityStartTime == 0) { generalAvailabilityStartTime = block.timestamp; } collection = _createNFTTimedEditionCollectionWithPaymentFactory({ name: collectionParams.name, symbol: collectionParams.symbol, tokenURI: collectionParams.tokenURI, mintEndTime: generalAvailabilityStartTime + fixedPriceSaleParams.saleDuration, approvedMinter: nftDropMarket, nonce: collectionParams.nonce, paymentAddressFactoryCall: paymentAddressFactoryCall }); FixedPriceSaleParams memory mappedFixedPriceSaleParams = FixedPriceSaleParams({ worldOrExhibitionId: fixedPriceSaleParams.worldOrExhibitionId, price: fixedPriceSaleParams.price, limitPerAccount: fixedPriceSaleParams.limitPerAccount, generalAvailabilityStartTime: fixedPriceSaleParams.generalAvailabilityStartTime }); _createFixedPriceSaleV3({ nftContract: collection, fixedPriceSaleParams: mappedFixedPriceSaleParams, // The deadline provided has already been validated above. txDeadlineTime: 0 }); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /** * @title A placeholder for any shared logic for NFT Market Router mixins. * @author HardlyDifficult */ abstract contract NFTMarketRouterCore {}
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "./apis/NFTDropMarketRouterAPIs.sol"; abstract contract NFTMarketRouterCreateFixedPriceSale is NFTDropMarketRouterAPIs { function createFixedPriceSale( address nftContract, FixedPriceSaleParams calldata fixedPriceSaleParams, uint256 txDeadlineTime ) external { _createFixedPriceSaleV3(nftContract, fixedPriceSaleParams, txDeadlineTime); } function createFixedPriceSaleWithEarlyAccessAllowlist( address nftContract, FixedPriceSaleParams calldata fixedPriceSaleParams, uint256 earlyAccessStartTime, bytes32 merkleRoot, string calldata merkleTreeUri, uint256 txDeadlineTime ) external { _createFixedPriceSaleWithEarlyAccessAllowlistV2( nftContract, fixedPriceSaleParams, earlyAccessStartTime, merkleRoot, merkleTreeUri, txDeadlineTime ); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import { NFTDropMarketRouterAPIs } from "./apis/NFTDropMarketRouterAPIs.sol"; abstract contract NFTMarketRouterDutchAuction is NFTDropMarketRouterAPIs { function createLinearDutchAuction( address nftContract, uint256 worldOrExhibitionId, uint256 maxPrice, uint256 minPrice, uint256 limitPerAccount, uint256 startTime, uint256 saleDuration ) external { _createLinearDutchAuction( nftContract, worldOrExhibitionId, maxPrice, minPrice, limitPerAccount, startTime, saleDuration ); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../interfaces/internal/INFTMarketGetters.sol"; import "./apis/NFTMarketRouterAPIs.sol"; error NFTMarketRouterList_Buy_Price_Set_But_Should_Set_Buy_Price_Is_False(); error NFTMarketRouterList_Duration_Set_Without_Reserve_Price(); error NFTMarketRouterList_Exhibition_Id_Set_Without_Prices(); error NFTMarketRouterList_Must_Set_Reserve_Or_Buy_Price(); error NFTMarketRouterList_Must_Set_Reserve_Buy_Price_Or_Exhibition(); error NFTMarketRouterList_Schedule_Set_Without_Prices(); error NFTMarketRouterList_Token_Ids_Not_Set(); /** * @title Offers value-added functions for listing NFTs in the NFTMarket contract. * @author batu-inal & HardlyDifficult & reggieag */ abstract contract NFTMarketRouterList is NFTMarketRouterAPIs { using RouteCallLibrary for address; /** * @notice [Deprecated] Use `batchListFromCollectionV3` instead. * Batch create reserve auction and/or set a buy price for many NFTs and escrow in the market contract. * A reserve auction price and/or a buy price must be set. * @param nftContract The address of the NFT contract. * @param tokenIds The ids of NFTs from the collection to set prices for. * @param worldOrExhibitionId The World NFT or exhibition ID the auctions are to be listed with. * Set this to 0 if n/a. * @param reservePrice The initial reserve price for the auctions created. * Set the reservePrice to 0 to skip creating auctions. * @param auctionDuration The duration of the auctions created. * Set this to 0 to use the default duration of 24 hours. * @param shouldSetBuyPrice True if buy prices should be set for these NFTs. * Set this to false to skip setting buy prices. 0 is a valid buy price enabling a giveaway. * @param buyPrice The price at which someone could buy these NFTs. * @return firstAuctionIdOfSequence 0 if reservePrice is 0, otherwise this is the id of the first auction listed. * The other auctions in the batch are listed sequentially from `first id` to `first id + count`. * @dev Notes: * a) Approval should be granted for the NFTMarket contract before using this function. * b) If any NFT is already listed for auction/buy now then the entire batch call will revert. */ function batchListFromCollectionV2( address nftContract, uint256[] calldata tokenIds, uint256 worldOrExhibitionId, uint256 reservePrice, uint256 auctionDuration, bool shouldSetBuyPrice, uint256 buyPrice ) public returns (uint256 firstAuctionIdOfSequence) { // Validate input. if (tokenIds.length == 0) { revert NFTMarketRouterList_Token_Ids_Not_Set(); } if (!shouldSetBuyPrice && buyPrice != 0) { revert NFTMarketRouterList_Buy_Price_Set_But_Should_Set_Buy_Price_Is_False(); } // List NFTs for sale. if (reservePrice != 0) { // Create auctions. // Process the first NFT in order to capture that auction ID as the return value. firstAuctionIdOfSequence = _createReserveAuctionV3( nftContract, tokenIds[0], worldOrExhibitionId, reservePrice, auctionDuration ); if (shouldSetBuyPrice) { // And set buy prices. _setBuyPriceV2(nftContract, tokenIds[0], worldOrExhibitionId, buyPrice); } for (uint256 i = 1; i < tokenIds.length; ) { _createReserveAuctionV3(nftContract, tokenIds[i], worldOrExhibitionId, reservePrice, auctionDuration); if (shouldSetBuyPrice) { _setBuyPriceV2(nftContract, tokenIds[i], worldOrExhibitionId, buyPrice); } unchecked { ++i; } } } else { // Set buy prices only (no auctions). if (auctionDuration != 0) { // Duration is only for auctions. revert NFTMarketRouterList_Duration_Set_Without_Reserve_Price(); } if (!shouldSetBuyPrice) { revert NFTMarketRouterList_Must_Set_Reserve_Or_Buy_Price(); } for (uint256 i = 0; i < tokenIds.length; ) { _setBuyPriceV2(nftContract, tokenIds[i], worldOrExhibitionId, buyPrice); unchecked { ++i; } } } } /** * @notice Batch create reserve auction and/or set a buy price for many NFTs and escrow in the market contract. * A reserve auction price and/or a buy price must be set. * @param nftContract The address of the NFT contract. * @param tokenIds The ids of NFTs from the collection to set prices for. * @param worldOrExhibitionId The World NFT or exhibition ID the auctions are to be listed with. * Set this to 0 if n/a. * @param reservePrice The initial reserve price for the auctions created. * Set the reservePrice to 0 to skip creating auctions. * @param auctionDuration The duration of the auctions created. * Set this to 0 to use the default duration of 24 hours. * @param shouldSetBuyPrice True if buy prices should be set for these NFTs. * Set this to false to skip setting buy prices. 0 is a valid buy price enabling a giveaway. * @param buyPrice The price at which someone could buy these NFTs. * @param saleStartsAt The time the sale should start at. 0 if the sale should start immediately. * @return firstAuctionIdOfSequence 0 if reservePrice is 0, otherwise this is the id of the first auction listed. * The other auctions in the batch are listed sequentially from `first id` to `first id + count`. * @dev Notes: * a) Approval should be granted for the NFTMarket contract before using this function. * b) If any NFT is already listed for auction then the entire batch call will revert. */ function batchListFromCollectionV3( address nftContract, uint256[] calldata tokenIds, uint256 worldOrExhibitionId, uint256 reservePrice, uint256 auctionDuration, bool shouldSetBuyPrice, uint256 buyPrice, uint256 saleStartsAt ) external returns (uint256 firstAuctionIdOfSequence) { firstAuctionIdOfSequence = batchListFromCollectionV2( nftContract, tokenIds, worldOrExhibitionId, reservePrice, auctionDuration, shouldSetBuyPrice, buyPrice ); for (uint256 i = 0; i < tokenIds.length; ) { _setSaleStartsAtAndIgnoreErrorIfStartsAtAlreadySet(nftContract, tokenIds[i], saleStartsAt); unchecked { ++i; } } } /** * @notice Create reserve auction, set a buy price, sale start at time, and/or set exhibition for an NFT and escrow in * the market contract. This will check the current state of the auction, buy now, exhibition, and schedule, then * update the values if they have changed. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT from the collection to set prices for. * @param worldOrExhibitionId The World NFT or exhibition ID to associate the listings to. * Set this to 0 if n/a. * @param reservePrice The initial reserve price for the auction created. * Set the reservePrice to 0 to skip creating auction. * @param auctionDuration The duration of the auction created. * Set this to 0 to use the default duration of 24 hours. * Note: if the auction was previously created, the duration will be ignored (it will not update to the new duration). * @param shouldSetBuyPrice True if buy prices should be set for this NFT. * Set this to false to skip setting buy prices, or if there is an existing buy price it will cancel it. * 0 is a valid buy price enabling a giveaway. * @param buyPrice The price at which someone could buy this NFT. * @param saleStartsAt The time the sale should start at. 0 if the sale should start immediately. * @dev Notes: * a) Approval should be granted for the NFTMarket contract before using this function. */ function upsertListingV2( address nftContract, uint256 tokenId, uint256 worldOrExhibitionId, uint256 reservePrice, uint256 auctionDuration, bool shouldSetBuyPrice, uint256 buyPrice, uint256 saleStartsAt ) external { if (!shouldSetBuyPrice && buyPrice != 0) { revert NFTMarketRouterList_Buy_Price_Set_But_Should_Set_Buy_Price_Is_False(); } if (!shouldSetBuyPrice && reservePrice == 0) { if (worldOrExhibitionId != 0) { // Attempting to set an exhibition without any listings. revert NFTMarketRouterList_Exhibition_Id_Set_Without_Prices(); } if (saleStartsAt != 0) { // If not listed, schedule is irrelevant. revert NFTMarketRouterList_Schedule_Set_Without_Prices(); } } // Attempting to cancel auction listing and update auction duration. if (reservePrice == 0 && auctionDuration != 0) { revert NFTMarketRouterList_Duration_Set_Without_Reserve_Price(); } uint256 auctionId = INFTMarketGetters(nftMarket).getReserveAuctionIdFor(nftContract, tokenId); uint256 currentReservePrice; if (auctionId != 0) { currentReservePrice = INFTMarketGetters(nftMarket).getReserveAuction(auctionId).amount; } (address buyPriceSeller, uint256 currentBuyPrice) = INFTMarketGetters(nftMarket).getBuyPrice(nftContract, tokenId); // Attempting to set no listings for the NFT when none exist. if ((currentReservePrice == 0 && reservePrice == 0) && (buyPriceSeller == address(0) && !shouldSetBuyPrice)) { revert NFTMarketRouterList_Must_Set_Reserve_Or_Buy_Price(); } // Attempting to keep the prices the same as they currently are. if ( currentReservePrice == reservePrice && ((!shouldSetBuyPrice && buyPriceSeller == address(0)) || (currentBuyPrice == buyPrice)) ) { uint256 currentExhibitionId = INFTMarketGetters(nftMarket).getExhibitionIdForNft(nftContract, tokenId); uint256 currentSaleStartsAt = INFTMarketGetters(nftMarket).getSaleStartsAt(nftContract, tokenId); bool updated; // Attempting to keep the exhibition the same as it is. if (currentExhibitionId != worldOrExhibitionId) { _updateNftExhibition(nftContract, tokenId, worldOrExhibitionId); updated = true; } if (currentSaleStartsAt != saleStartsAt) { _setSaleStartsAt(nftContract, tokenId, saleStartsAt); updated = true; } if (!updated) { revert NFTMarketRouterList_Must_Set_Reserve_Buy_Price_Or_Exhibition(); } } else { // Attempting to update at least one price. // Attempting to set a reserve price. if (reservePrice != 0) { // There is an already existing auction. if (currentReservePrice != 0) { // The current reserve price does not match the new reserve price, // so update the already existing auction. if (currentReservePrice != reservePrice) { _updateReserveAuctionV2(auctionId, worldOrExhibitionId, reservePrice); } // It may be nice to revert if the specified auction duration does not match the current auction duration, // until we are able to change durations. (alt cancel and recreate the auction) } else { // There is no auction currently in place, so create one. _createReserveAuctionV3(nftContract, tokenId, worldOrExhibitionId, reservePrice, auctionDuration); } } // Attempting to set a buy now price if (shouldSetBuyPrice) { // Only set a new buy now price if it does not match the current price. if (currentBuyPrice != buyPrice) { _setBuyPriceV2(nftContract, tokenId, worldOrExhibitionId, buyPrice); } } if (shouldSetBuyPrice || reservePrice != 0) { uint256 currentSaleStartsAt = INFTMarketGetters(nftMarket).getSaleStartsAt(nftContract, tokenId); if (currentSaleStartsAt != saleStartsAt) { _setSaleStartsAt(nftContract, tokenId, saleStartsAt); } } // Cancel reserve or buy prices // We do this at the end of the function so that we keep the item in escrow until all prices are set // Attempting to set no reserve price // If there is an existing auction, cancel it. if (reservePrice == 0 && currentReservePrice != 0) { _cancelReserveAuction(auctionId); } // Attempting to set no buy now price // If there is an existing buy now, cancel it. if (!shouldSetBuyPrice && buyPriceSeller != address(0)) { _cancelBuyPrice(nftContract, tokenId); } } } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "./apis/WorldsNftRouterAPIs.sol"; error NFTMarketRouterWorldsNftUserRoles_No_User_Role_Actions(); /** * @title Offers value-added functions for managing user roles in the Worlds contract. * @author reggieag */ abstract contract NFTMarketRouterWorldsNftUserRoles is WorldsNftRouterAPIs { /// @notice The action to take for a user role. enum RoleAction { RevokeAllRoles, SetAdmin, SetEditor } /// @notice A user and the role action to take for that user. struct UserRoleAction { address user; RoleAction roleAction; } /** * Manages user roles for a world in bulk. * The caller can set an editor role, or an admin role, or revoke all roles for a user. * The `RoleAction` enum is used to specify the action to take for each user. * @param worldId The address of the NFT contract. * @param userRoleActions The user addresses and the role actions to take for that user. * @dev Notes: * a) The caller of this function must have an admin role or be the owner of the world. * b) Cannot set a role for a user if they already have that same role granted. For example, cannot set * an editor role for a user if they already have an editor role. */ function manageWorldRolesForUsers(uint256 worldId, UserRoleAction[] calldata userRoleActions) external { if (userRoleActions.length == 0) { revert NFTMarketRouterWorldsNftUserRoles_No_User_Role_Actions(); } for (uint256 i = 0; i < userRoleActions.length; ) { if (userRoleActions[i].roleAction == RoleAction.RevokeAllRoles) { _revokeAllRolesForUser(worldId, userRoleActions[i].user); } else if (userRoleActions[i].roleAction == RoleAction.SetAdmin) { _setAdminRole(worldId, userRoleActions[i].user); } else { // if (userRoleActions[i].roleAction == RoleAction.SetEditor) _setEditorRole(worldId, userRoleActions[i].user); } unchecked { ++i; } } } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /// Constant values shared across mixins. /** * @dev 100% in basis points. */ uint256 constant BASIS_POINTS = 10_000; /** * @dev The default admin role defined by OZ ACL modules. */ bytes32 constant DEFAULT_ADMIN_ROLE = 0x00; //////////////////////////////////////////////////////////////// // Royalties & Take Rates //////////////////////////////////////////////////////////////// /** * @dev The max take rate an exhibition can have. */ uint256 constant MAX_WORLD_TAKE_RATE = 5_000; /** * @dev Cap the number of royalty recipients. * A cap is required to ensure gas costs are not too high when a sale is settled. */ uint256 constant MAX_ROYALTY_RECIPIENTS = 5; /** * @dev Default royalty cut paid out on secondary sales. * Set to 10% of the secondary sale. */ uint96 constant ROYALTY_IN_BASIS_POINTS = 1_000; /** * @dev Reward paid to referrers when a sale is made. * Set to 1% of the sale amount. This 1% is deducted from the protocol fee. */ uint96 constant BUY_REFERRER_IN_BASIS_POINTS = 100; /** * @dev 10%, expressed as a denominator for more efficient calculations. */ uint256 constant ROYALTY_RATIO = BASIS_POINTS / ROYALTY_IN_BASIS_POINTS; /** * @dev 1%, expressed as a denominator for more efficient calculations. */ uint256 constant BUY_REFERRER_RATIO = BASIS_POINTS / BUY_REFERRER_IN_BASIS_POINTS; //////////////////////////////////////////////////////////////// // Gas Limits //////////////////////////////////////////////////////////////// /** * @dev The gas limit used when making external read-only calls. * This helps to ensure that external calls does not prevent the market from executing. */ uint256 constant READ_ONLY_GAS_LIMIT = 40_000; /** * @dev The gas limit to send ETH to multiple recipients, enough for a 5-way split. */ uint256 constant SEND_VALUE_GAS_LIMIT_MULTIPLE_RECIPIENTS = 210_000; /** * @dev The gas limit to send ETH to a single recipient, enough for a contract with a simple receiver. */ uint256 constant SEND_VALUE_GAS_LIMIT_SINGLE_RECIPIENT = 20_000; //////////////////////////////////////////////////////////////// // Collection Type Names //////////////////////////////////////////////////////////////// /** * @dev The NFT collection type. */ string constant NFT_COLLECTION_TYPE = "NFT Collection"; /** * @dev The NFT drop collection type. */ string constant NFT_DROP_COLLECTION_TYPE = "NFT Drop Collection"; /** * @dev The NFT timed edition collection type. */ string constant NFT_TIMED_EDITION_COLLECTION_TYPE = "NFT Timed Edition Collection"; /** * @dev The NFT limited edition collection type. */ string constant NFT_LIMITED_EDITION_COLLECTION_TYPE = "NFT Limited Edition Collection"; //////////////////////////////////////////////////////////////// // Business Logic //////////////////////////////////////////////////////////////// /** * @dev Limits scheduled start/end times to be less than 2 years in the future. */ uint256 constant MAX_SCHEDULED_TIME_IN_THE_FUTURE = 365 days * 2; /** * @dev The minimum increase of 10% required when making an offer or placing a bid. */ uint256 constant MIN_PERCENT_INCREMENT_DENOMINATOR = BASIS_POINTS / 1_000; /** * @dev Protocol fee for edition mints in basis points. */ uint256 constant EDITION_PROTOCOL_FEE_IN_BASIS_POINTS = 500; /** * @dev Hash of the edition type names. * This is precalculated in order to save gas on use. * `keccak256(abi.encodePacked(NFT_TIMED_EDITION_COLLECTION_TYPE))` */ bytes32 constant timedEditionTypeHash = 0xee2afa3f960e108aca17013728aafa363a0f4485661d9b6f41c6b4ddb55008ee; bytes32 constant limitedEditionTypeHash = 0x7df1f68d01ab1a6ee0448a4c3fbda832177331ff72c471b12b0051c96742eef5;
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "../../interfaces/internal/IFethMarket.sol"; error FETHNode_FETH_Address_Is_Not_A_Contract(); error FETHNode_Only_FETH_Can_Transfer_ETH(); /** * @title A mixin for interacting with the FETH contract. * @author batu-inal & HardlyDifficult */ abstract contract FETHNode is ContextUpgradeable { using AddressUpgradeable for address; using AddressUpgradeable for address payable; /// @notice The FETH ERC-20 token for managing escrow and lockup. IFethMarket internal immutable feth; constructor(address _feth) { if (!_feth.isContract()) { revert FETHNode_FETH_Address_Is_Not_A_Contract(); } feth = IFethMarket(_feth); } /** * @notice Only used by FETH. Any direct transfer from users will revert. */ receive() external payable { if (msg.sender != address(feth)) { revert FETHNode_Only_FETH_Can_Transfer_ETH(); } } /** * @notice Withdraw the msg.sender's available FETH balance if they requested more than the msg.value provided. * @dev This may revert if the msg.sender is non-receivable. * This helper should not be used anywhere that may lead to locked assets. * @param totalAmount The total amount of ETH required (including the msg.value). * @param shouldRefundSurplus If true, refund msg.value - totalAmount to the msg.sender. */ function _tryUseFETHBalance(uint256 totalAmount, bool shouldRefundSurplus) internal { if (totalAmount > msg.value) { // Withdraw additional ETH required from the user's available FETH balance. unchecked { // The if above ensures delta will not underflow. // Withdraw ETH from the user's account in the FETH token contract, // making the funds available in this contract as ETH. feth.marketWithdrawFrom(_msgSender(), totalAmount - msg.value); } } else if (shouldRefundSurplus && totalAmount < msg.value) { // Return any surplus ETH to the user. unchecked { // The if above ensures this will not underflow payable(_msgSender()).sendValue(msg.value - totalAmount); } } } /** * @notice Gets the FETH contract used to escrow offer funds. * @return fethAddress The FETH contract address. */ function getFethAddress() external view returns (address fethAddress) { fethAddress = address(feth); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "../../interfaces/internal/roles/IAdminRole.sol"; import "../../interfaces/internal/roles/IOperatorRole.sol"; error FoundationTreasuryNode_Address_Is_Not_A_Contract(); error FoundationTreasuryNode_Caller_Not_Admin(); error FoundationTreasuryNode_Caller_Not_Operator(); /** * @title Stores a reference to Foundation's treasury contract for other mixins to leverage. * @notice The treasury collects fees and defines admin/operator roles. * @author batu-inal & HardlyDifficult */ abstract contract FoundationTreasuryNodeV1 is Initializable { using AddressUpgradeable for address payable; /// @dev This value was replaced with an immutable version. address payable private __gap_was_treasury; /// @notice The address of the treasury contract. address payable private immutable treasury; /// @notice Requires the caller is a Foundation admin. modifier onlyFoundationAdmin() { if (!IAdminRole(treasury).isAdmin(msg.sender)) { revert FoundationTreasuryNode_Caller_Not_Admin(); } _; } /// @notice Requires the caller is a Foundation operator. modifier onlyFoundationOperator() { if (!IOperatorRole(treasury).isOperator(msg.sender)) { revert FoundationTreasuryNode_Caller_Not_Operator(); } _; } /** * @notice Set immutable variables for the implementation contract. * @dev Assigns the treasury contract address. */ constructor(address payable _treasury) { if (!_treasury.isContract()) { revert FoundationTreasuryNode_Address_Is_Not_A_Contract(); } treasury = _treasury; } /** * @notice Gets the Foundation treasury contract. * @dev This call is used in the royalty registry contract. * @return treasuryAddress The address of the Foundation treasury contract. */ function getFoundationTreasury() public view returns (address payable treasuryAddress) { treasuryAddress = treasury; } /** * @notice This empty reserved space is put in place to allow future versions to add new variables without shifting * down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps * @dev This mixin uses a total of 2,001 slots. */ uint256[2_000] private __gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "../../interfaces/internal/INFTCollectionType.sol"; import "../../interfaces/internal/IMarketUtils.sol"; import "./Constants.sol"; import "./FoundationTreasuryNodeV1.sol"; import "./MarketSharedCore.sol"; import "./MarketStructs.sol"; import "./SendValueWithFallbackWithdraw.sol"; error NFTMarketFees_Market_Utils_Is_Not_A_Contract(); error NFTMarketFees_Invalid_Protocol_Fee(); /** * @title A mixin to distribute funds when an NFT is sold. * @author batu-inal & HardlyDifficult */ abstract contract MarketFees is FoundationTreasuryNodeV1, ContextUpgradeable, MarketSharedCore, SendValueWithFallbackWithdraw { using AddressUpgradeable for address; /** * @dev Removing old unused variables in an upgrade safe way. Was: * uint256 private _primaryFoundationFeeBasisPoints; * uint256 private _secondaryFoundationFeeBasisPoints; * uint256 private _secondaryCreatorFeeBasisPoints; * mapping(address => mapping(uint256 => bool)) private _nftContractToTokenIdToFirstSaleCompleted; */ uint256[4] private __gap_was_fees; /// @notice True for the Drop market which only performs primary sales. False if primary & secondary are supported. bool private immutable assumePrimarySale; /// @notice The fee collected by Foundation for sales facilitated by this market contract. uint256 private immutable defaultProtocolFeeInBasisPoints; /// @notice Reference to our MarketUtils contract. IMarketUtils private immutable marketUtils; /** * @notice Emitted when an NFT sold with a referrer. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT. * @param buyReferrer The account which received the buy referral incentive. * @param buyReferrerFee The portion of the protocol fee collected by the buy referrer. * @param buyReferrerSellerFee The portion of the owner revenue collected by the buy referrer (not implemented). */ event BuyReferralPaid( address indexed nftContract, uint256 indexed tokenId, address buyReferrer, uint256 buyReferrerFee, uint256 buyReferrerSellerFee ); /** * @notice Emitted when an NFT is sold when associated with a sell referrer. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT. * @param sellerReferrer The account which received the sell referral incentive. * @param sellerReferrerFee The portion of the seller revenue collected by the sell referrer. */ event SellerReferralPaid( address indexed nftContract, uint256 indexed tokenId, address sellerReferrer, uint256 sellerReferrerFee ); /** * @notice Sets the immutable variables for this contract. * @param _defaultProtocolFeeInBasisPoints The default protocol fee to use for this market. * @param marketUtilsAddress The address to use for our MarketUtils contract. * @param _assumePrimarySale True for the Drop market which only performs primary sales. * False if primary & secondary are supported. */ constructor(uint16 _defaultProtocolFeeInBasisPoints, address marketUtilsAddress, bool _assumePrimarySale) { if ( _defaultProtocolFeeInBasisPoints < BASIS_POINTS / BUY_REFERRER_RATIO || _defaultProtocolFeeInBasisPoints + BASIS_POINTS / ROYALTY_RATIO >= BASIS_POINTS - MAX_WORLD_TAKE_RATE ) { /* If the protocol fee is invalid, revert: * Protocol fee must be greater than the buy referrer fee since referrer fees are deducted from the protocol fee. * The protocol fee must leave room for the creator royalties and the max exhibition take rate. */ revert NFTMarketFees_Invalid_Protocol_Fee(); } if (!marketUtilsAddress.isContract()) { revert NFTMarketFees_Market_Utils_Is_Not_A_Contract(); } assumePrimarySale = _assumePrimarySale; defaultProtocolFeeInBasisPoints = _defaultProtocolFeeInBasisPoints; marketUtils = IMarketUtils(marketUtilsAddress); } /** * @notice Distributes funds to foundation, creator recipients, and NFT owner after a sale. * @dev `virtual` allows other mixins to be notified anytime a sale occurs. */ function _distributeFunds( address nftContract, uint256 tokenId, address payable seller, uint256 price, address payable buyReferrer, address payable sellerReferrerPaymentAddress, uint16 sellerReferrerTakeRateInBasisPoints ) internal virtual returns (uint256 totalFees, uint256 creatorRev, uint256 sellerRev) { if (price == 0) { // When the sale price is 0, there are no revenue to distribute. return (0, 0, 0); } address payable[] memory creatorRecipients; uint256[] memory creatorShares; uint256 buyReferrerFee; uint256 sellerReferrerFee; (totalFees, creatorRecipients, creatorShares, sellerRev, buyReferrerFee, sellerReferrerFee) = getFees( nftContract, tokenId, seller, price, buyReferrer, sellerReferrerTakeRateInBasisPoints ); // Pay the creator(s) // If just a single recipient was defined, use a larger gas limit in order to support in-contract split logic. uint256 creatorGasLimit = creatorRecipients.length == 1 ? SEND_VALUE_GAS_LIMIT_MULTIPLE_RECIPIENTS : SEND_VALUE_GAS_LIMIT_SINGLE_RECIPIENT; unchecked { for (uint256 i = 0; i < creatorRecipients.length; ++i) { _sendValueWithFallbackWithdraw(creatorRecipients[i], creatorShares[i], creatorGasLimit); // Sum the total creator rev from shares // creatorShares is in ETH so creatorRev will not overflow here. creatorRev += creatorShares[i]; } } // Pay the seller _sendValueWithFallbackWithdraw(seller, sellerRev, SEND_VALUE_GAS_LIMIT_SINGLE_RECIPIENT); // Pay the protocol fee _sendValueWithFallbackWithdraw(getFoundationTreasury(), totalFees, SEND_VALUE_GAS_LIMIT_SINGLE_RECIPIENT); // Pay the buy referrer fee if (buyReferrerFee != 0) { _sendValueWithFallbackWithdraw(buyReferrer, buyReferrerFee, SEND_VALUE_GAS_LIMIT_SINGLE_RECIPIENT); emit BuyReferralPaid({ nftContract: nftContract, tokenId: tokenId, buyReferrer: buyReferrer, buyReferrerFee: buyReferrerFee, buyReferrerSellerFee: 0 }); unchecked { // Add the referrer fee back into the total fees so that all 3 return fields sum to the total price for events totalFees += buyReferrerFee; } } if (sellerReferrerPaymentAddress != address(0)) { if (sellerReferrerFee != 0) { // Add the seller referrer fee back to revenue so that all 3 return fields sum to the total price for events. unchecked { if (sellerRev == 0) { // When sellerRev is 0, this is a primary sale and all revenue is attributed to the "creator". creatorRev += sellerReferrerFee; } else { sellerRev += sellerReferrerFee; } } _sendValueWithFallbackWithdraw( sellerReferrerPaymentAddress, sellerReferrerFee, SEND_VALUE_GAS_LIMIT_SINGLE_RECIPIENT ); } emit SellerReferralPaid(nftContract, tokenId, sellerReferrerPaymentAddress, sellerReferrerFee); } } /** * @notice Calculates how funds should be distributed for the given sale details. * @dev When the NFT is being sold by the `tokenCreator`, all the seller revenue will * be split with the royalty recipients defined for that NFT. */ function getFees( address nftContract, uint256 tokenId, address payable seller, uint256 price, address payable buyReferrer, uint16 sellerReferrerTakeRateInBasisPoints ) public view returns ( uint256 protocolFeeAmount, address payable[] memory creatorRecipients, uint256[] memory creatorShares, uint256 sellerRev, uint256 buyReferrerFee, uint256 sellerReferrerFee ) { MarketTransactionOptions memory options = MarketTransactionOptions({ // Market info marketTakeRateInBasisPoints: _getProtocolFee(nftContract), assumePrimarySale: assumePrimarySale, // Sale info nftContract: nftContract, tokenId: tokenId, price: price, seller: seller, // Referrals buyReferrer: buyReferrer, sellerReferrerTakeRateInBasisPoints: sellerReferrerTakeRateInBasisPoints, // Transaction info sender: _msgSender() }); (protocolFeeAmount, creatorRecipients, creatorShares, sellerRev, buyReferrerFee, sellerReferrerFee) = marketUtils .getTransactionBreakdown(options); } /** * @notice Returns how funds will be distributed for a sale at the given price point. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT. * @param price The sale price to calculate the fees for. * @return totalFees How much will be sent to the Foundation treasury and/or referrals. * @return creatorRev How much will be sent across all the `creatorRecipients` defined. * @return creatorRecipients The addresses of the recipients to receive a portion of the creator fee. * @return creatorShares The percentage of the creator fee to be distributed to each `creatorRecipient`. * If there is only one `creatorRecipient`, this may be an empty array. * Otherwise `creatorShares.length` == `creatorRecipients.length`. * @return sellerRev How much will be sent to the owner/seller of the NFT. * If the NFT is being sold by the creator, this may be 0 and the full revenue will appear as `creatorRev`. * @return seller The address of the owner of the NFT. * If `sellerRev` is 0, this may be `address(0)`. * @dev Currently in use by the FNDMiddleware `getFees` call (now deprecated). */ function getFeesAndRecipients( address nftContract, uint256 tokenId, uint256 price ) external view returns ( uint256 totalFees, uint256 creatorRev, address payable[] memory creatorRecipients, uint256[] memory creatorShares, uint256 sellerRev, address payable seller ) { seller = _getSellerOrOwnerOf(nftContract, tokenId); (totalFees, creatorRecipients, creatorShares, sellerRev, , ) = getFees({ nftContract: nftContract, tokenId: tokenId, seller: seller, price: price, // Notice: Setting this value is a breaking change for the FNDMiddleware contract. // Will be wired in an upcoming release to communicate the buy referral information. buyReferrer: payable(0), sellerReferrerTakeRateInBasisPoints: 0 }); // Sum the total creator rev from shares unchecked { for (uint256 i = 0; i < creatorShares.length; ++i) { creatorRev += creatorShares[i]; } } } /** * @notice returns the address of the MarketUtils contract. */ function getMarketUtilsAddress() external view returns (address marketUtilsAddress) { marketUtilsAddress = address(marketUtils); } /** * @notice Calculates the protocol fee for the given NFT contract. * @dev This returns the contract's default fee but may be overridden to change fees based on the collection type. */ function _getProtocolFee(address /* nftContract */) internal view virtual returns (uint256 protocolFeeInBasisPoints) { protocolFeeInBasisPoints = defaultProtocolFeeInBasisPoints; } /** * @notice This empty reserved space is put in place to allow future versions to add new variables without shifting * down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps * @dev This mixins uses 504 slots in total. */ uint256[500] private __gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "./FETHNode.sol"; /** * @title A place for common modifiers and functions used by various market mixins, if any. * @dev This also leaves a gap which can be used to add a new mixin to the top of the inheritance tree. * @author batu-inal & HardlyDifficult */ abstract contract MarketSharedCore is FETHNode { /** * @notice Checks who the seller for an NFT is if listed in this market. * @param nftContract The address of the NFT contract. * @param tokenId The id of the NFT. * @return seller The seller which listed this NFT for sale, or address(0) if not listed. */ function getSellerOf(address nftContract, uint256 tokenId) external view returns (address payable seller) { seller = _getSellerOf(nftContract, tokenId); } /** * @notice Checks who the seller for an NFT is if listed in this market. */ function _getSellerOf(address nftContract, uint256 tokenId) internal view virtual returns (address payable seller) { // Returns address(0) by default. } /** * @notice Checks who the seller for an NFT is if listed in this market or returns the current owner. */ function _getSellerOrOwnerOf( address nftContract, uint256 tokenId ) internal view virtual returns (address payable sellerOrOwner); /** * @notice This empty reserved space is put in place to allow future versions to add new variables without shifting * down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[450] private __gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; /// @notice Details about a marketplace sale. struct MarketTransactionOptions { //////////////////////////////////////////////////////////////// // Market config //////////////////////////////////////////////////////////////// /// @notice Percentage of the transaction to go the the market, expressed in basis points. uint256 marketTakeRateInBasisPoints; /// @notice set to true when the token is being sold by it's creator bool assumePrimarySale; //////////////////////////////////////////////////////////////// // Sale info //////////////////////////////////////////////////////////////// /// @notice The contract address of the nft address nftContract; /// @notice The token id of the nft. uint256 tokenId; /// @notice price at which the token is being sold uint256 price; /// @notice address of the account that is selling the token address payable seller; //////////////////////////////////////////////////////////////// // Referrals //////////////////////////////////////////////////////////////// /// @notice Address of the account that referred the buyer. address payable buyReferrer; /// @notice Percentage of the transaction to go the the account which referred the seller, expressed in basis points. uint16 sellerReferrerTakeRateInBasisPoints; //////////////////////////////////////////////////////////////// // Transaction info //////////////////////////////////////////////////////////////// /// @notice The msg.sender which executed the purchase transaction. address sender; } /// @notice The auction configuration for a specific NFT. struct ReserveAuction { /// @notice The address of the NFT contract. address nftContract; /// @notice The id of the NFT. uint256 tokenId; /// @notice The owner of the NFT which listed it in auction. address payable seller; /// @notice The duration for this auction. uint256 duration; /// @notice The extension window for this auction. uint256 extensionDuration; /// @notice The time at which this auction will not accept any new bids. /// @dev This is `0` until the first bid is placed. uint256 endTime; /// @notice The current highest bidder in this auction. /// @dev This is `address(0)` until the first bid is placed. address payable bidder; /// @notice The latest price of the NFT in this auction. /// @dev This is set to the reserve price, and then to the highest bid once the auction has started. uint256 amount; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; error NFTCollectionFactoryNode_Address_Is_Not_A_Contract(); /** * @title Stores a reference to Foundation's NFTCollectionFactory contract for other mixins to leverage. * @author HardlyDifficult */ abstract contract NFTCollectionFactoryNode { using AddressUpgradeable for address; address internal immutable nftCollectionFactory; constructor(address _nftCollectionFactory) { if (!_nftCollectionFactory.isContract()) { revert NFTCollectionFactoryNode_Address_Is_Not_A_Contract(); } nftCollectionFactory = _nftCollectionFactory; } /** * @notice Returns the address of the NFTMarket contract. */ function getNftCollectionFactoryAddress() external view returns (address factory) { factory = nftCollectionFactory; } // This mixin uses 0 slots. }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; /** * @title Stores a reference to Foundation's NFTDropMarket contract for other mixins to leverage. * @author HardlyDifficult */ abstract contract NFTDropMarketNode { using AddressUpgradeable for address; address internal immutable nftDropMarket; error NFTDropMarketNode_Address_Is_Not_A_Contract(); constructor(address _nftDropMarket) { if (!_nftDropMarket.isContract()) { revert NFTDropMarketNode_Address_Is_Not_A_Contract(); } nftDropMarket = _nftDropMarket; } /** * @notice Returns the address of the NFTDropMarket contract. */ function getNftDropMarketAddress() external view returns (address market) { market = nftDropMarket; } // This mixin uses 0 slots. }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; /** * @title Stores a reference to Foundation's NFTMarket contract for other mixins to leverage. * @author HardlyDifficult */ abstract contract NFTMarketNode { using AddressUpgradeable for address; address internal immutable nftMarket; error NFTMarketNode_Address_Is_Not_A_Contract(); constructor(address _nftMarket) { if (!_nftMarket.isContract()) { revert NFTMarketNode_Address_Is_Not_A_Contract(); } nftMarket = _nftMarket; } /** * @notice Returns the address of the NFTMarket contract. */ function getNftMarketAddress() external view returns (address market) { market = nftMarket; } // This mixin uses 0 slots. }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "./FETHNode.sol"; import "./FoundationTreasuryNodeV1.sol"; /** * @title A mixin for sending ETH with a fallback withdraw mechanism. * @notice Attempt to send ETH and if the transfer fails or runs out of gas, store the balance * in the FETH token contract for future withdrawal instead. * @dev This mixin was recently switched to escrow funds in FETH. * Once we have confirmed all pending balances have been withdrawn, we can remove the escrow tracking here. * @author batu-inal & HardlyDifficult */ abstract contract SendValueWithFallbackWithdraw is FoundationTreasuryNodeV1, FETHNode { using AddressUpgradeable for address payable; /// @dev Removing old unused variables in an upgrade safe way. uint256 private __gap_was_pendingWithdrawals; /** * @notice Emitted when escrowed funds are withdrawn to FETH. * @param user The account which has withdrawn ETH. * @param amount The amount of ETH which has been withdrawn. */ event WithdrawalToFETH(address indexed user, uint256 amount); /** * @notice Attempt to send a user or contract ETH. * If it fails store the amount owned for later withdrawal in FETH. * @dev This may fail when sending ETH to a contract that is non-receivable or exceeds the gas limit specified. */ function _sendValueWithFallbackWithdraw(address payable user, uint256 amount, uint256 gasLimit) internal { if (amount == 0) { return; } if (user == address(feth)) { // FETH may revert on ETH transfers and will reject `depositFor` calls to itself, so redirect funds to the // treasury contract instead. user = getFoundationTreasury(); } // Cap the gas to prevent consuming all available gas to block a tx from completing successfully // solhint-disable-next-line avoid-low-level-calls (bool success, ) = user.call{ value: amount, gas: gasLimit }(""); if (!success) { // Store the funds that failed to send for the user in the FETH token feth.depositFor{ value: amount }(user); emit WithdrawalToFETH(user, amount); } } /** * @notice This empty reserved space is put in place to allow future versions to add new variables without shifting * down storage in the inheritance chain. See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[999] private __gap; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "../../libraries/TimeLibrary.sol"; error TxDeadline_Tx_Deadline_Expired(); /** * @title A mixin that provides a modifier to check that a transaction deadline has not expired. * @author HardlyDifficult */ abstract contract TxDeadline { using TimeLibrary for uint256; /// @notice Requires the deadline provided is 0, now, or in the future. modifier txDeadlineNotExpired(uint256 txDeadlineTime) { // No transaction deadline when set to 0. if (txDeadlineTime != 0 && txDeadlineTime.hasExpired()) { revert TxDeadline_Tx_Deadline_Expired(); } _; } // This mixin does not use any storage. }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; error WorldsNftNode_Worlds_NFT_Is_Not_A_Contract(); /** * @title Stores a reference to the Worlds NFT contract for contracts to leverage. * @author HardlyDifficult */ abstract contract WorldsNftNode { using AddressUpgradeable for address; address internal immutable worlds; constructor(address worldsNft) { if (!worldsNft.isContract()) { revert WorldsNftNode_Worlds_NFT_Is_Not_A_Contract(); } worlds = worldsNft; } /** * @notice Returns the address of the Worlds NFT contract. */ function getWorldsNftAddress() external view returns (address worldsNft) { worldsNft = worlds; } // This mixin uses 0 slots. }
{ "evmVersion": "shanghai", "optimizer": { "enabled": true, "runs": 1337000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_nftMarket","type":"address"},{"internalType":"address","name":"_nftDropMarket","type":"address"},{"internalType":"address","name":"_nftCollectionFactory","type":"address"},{"internalType":"address","name":"_worlds","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NFTCollectionFactoryNode_Address_Is_Not_A_Contract","type":"error"},{"inputs":[],"name":"NFTCreateAndListTimedEditionCollection_Sale_Duration_Cannot_Be_Zero","type":"error"},{"inputs":[],"name":"NFTDropMarketNode_Address_Is_Not_A_Contract","type":"error"},{"inputs":[],"name":"NFTMarketNode_Address_Is_Not_A_Contract","type":"error"},{"inputs":[],"name":"NFTMarketRouterList_Buy_Price_Set_But_Should_Set_Buy_Price_Is_False","type":"error"},{"inputs":[],"name":"NFTMarketRouterList_Duration_Set_Without_Reserve_Price","type":"error"},{"inputs":[],"name":"NFTMarketRouterList_Exhibition_Id_Set_Without_Prices","type":"error"},{"inputs":[],"name":"NFTMarketRouterList_Must_Set_Reserve_Buy_Price_Or_Exhibition","type":"error"},{"inputs":[],"name":"NFTMarketRouterList_Must_Set_Reserve_Or_Buy_Price","type":"error"},{"inputs":[],"name":"NFTMarketRouterList_Schedule_Set_Without_Prices","type":"error"},{"inputs":[],"name":"NFTMarketRouterList_Token_Ids_Not_Set","type":"error"},{"inputs":[],"name":"NFTMarketRouterWorldsNftUserRoles_No_User_Role_Actions","type":"error"},{"inputs":[],"name":"RouteCallLibrary_Call_Failed_Without_Revert_Reason","type":"error"},{"inputs":[],"name":"TxDeadline_Tx_Deadline_Expired","type":"error"},{"inputs":[],"name":"WorldsNftNode_Worlds_NFT_Is_Not_A_Contract","type":"error"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"auctionDuration","type":"uint256"},{"internalType":"bool","name":"shouldSetBuyPrice","type":"bool"},{"internalType":"uint256","name":"buyPrice","type":"uint256"}],"name":"batchListFromCollectionV2","outputs":[{"internalType":"uint256","name":"firstAuctionIdOfSequence","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"auctionDuration","type":"uint256"},{"internalType":"bool","name":"shouldSetBuyPrice","type":"bool"},{"internalType":"uint256","name":"buyPrice","type":"uint256"},{"internalType":"uint256","name":"saleStartsAt","type":"uint256"}],"name":"batchListFromCollectionV3","outputs":[{"internalType":"uint256","name":"firstAuctionIdOfSequence","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"components":[{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limitPerAccount","type":"uint256"},{"internalType":"uint256","name":"generalAvailabilityStartTime","type":"uint256"}],"internalType":"struct FixedPriceSaleParams","name":"fixedPriceSaleParams","type":"tuple"},{"internalType":"uint256","name":"txDeadlineTime","type":"uint256"}],"name":"createFixedPriceSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"components":[{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limitPerAccount","type":"uint256"},{"internalType":"uint256","name":"generalAvailabilityStartTime","type":"uint256"}],"internalType":"struct FixedPriceSaleParams","name":"fixedPriceSaleParams","type":"tuple"},{"internalType":"uint256","name":"earlyAccessStartTime","type":"uint256"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"string","name":"merkleTreeUri","type":"string"},{"internalType":"uint256","name":"txDeadlineTime","type":"uint256"}],"name":"createFixedPriceSaleWithEarlyAccessAllowlist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"uint32","name":"maxTokenId","type":"uint32"},{"internalType":"uint96","name":"nonce","type":"uint96"}],"internalType":"struct LimitedEditionCollectionCreationParams","name":"collectionParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limitPerAccount","type":"uint256"},{"internalType":"uint256","name":"generalAvailabilityStartTime","type":"uint256"}],"internalType":"struct FixedPriceSaleParams","name":"fixedPriceSaleParams","type":"tuple"},{"internalType":"uint256","name":"txDeadlineTime","type":"uint256"}],"name":"createLimitedEditionCollectionAndFixedPriceSale","outputs":[{"internalType":"address","name":"collection","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"uint32","name":"maxTokenId","type":"uint32"},{"internalType":"uint96","name":"nonce","type":"uint96"}],"internalType":"struct LimitedEditionCollectionCreationParams","name":"collectionParams","type":"tuple"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct CallWithoutValue","name":"paymentAddressFactoryCall","type":"tuple"},{"components":[{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limitPerAccount","type":"uint256"},{"internalType":"uint256","name":"generalAvailabilityStartTime","type":"uint256"}],"internalType":"struct FixedPriceSaleParams","name":"fixedPriceSaleParams","type":"tuple"},{"internalType":"uint256","name":"txDeadlineTime","type":"uint256"}],"name":"createLimitedEditionCollectionAndFixedPriceSaleWithPaymentFactory","outputs":[{"internalType":"address","name":"collection","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"uint256","name":"limitPerAccount","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"saleDuration","type":"uint256"}],"name":"createLinearDutchAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"uint96","name":"nonce","type":"uint96"}],"internalType":"struct TimedEditionCollectionCreationParams","name":"collectionParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limitPerAccount","type":"uint256"},{"internalType":"uint256","name":"generalAvailabilityStartTime","type":"uint256"},{"internalType":"uint256","name":"saleDuration","type":"uint256"}],"internalType":"struct FixedPriceSaleParamsV2","name":"fixedPriceSaleParams","type":"tuple"},{"internalType":"uint256","name":"txDeadlineTime","type":"uint256"}],"name":"createTimedEditionCollectionAndFixedPriceSaleV2","outputs":[{"internalType":"address","name":"collection","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"string","name":"tokenURI","type":"string"},{"internalType":"uint96","name":"nonce","type":"uint96"}],"internalType":"struct TimedEditionCollectionCreationParams","name":"collectionParams","type":"tuple"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct CallWithoutValue","name":"paymentAddressFactoryCall","type":"tuple"},{"components":[{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"limitPerAccount","type":"uint256"},{"internalType":"uint256","name":"generalAvailabilityStartTime","type":"uint256"},{"internalType":"uint256","name":"saleDuration","type":"uint256"}],"internalType":"struct FixedPriceSaleParamsV2","name":"fixedPriceSaleParams","type":"tuple"},{"internalType":"uint256","name":"txDeadlineTime","type":"uint256"}],"name":"createTimedEditionCollectionAndFixedPriceSaleWithPaymentFactoryV2","outputs":[{"internalType":"address","name":"collection","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getNftCollectionFactoryAddress","outputs":[{"internalType":"address","name":"factory","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNftDropMarketAddress","outputs":[{"internalType":"address","name":"market","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNftMarketAddress","outputs":[{"internalType":"address","name":"market","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWorldsNftAddress","outputs":[{"internalType":"address","name":"worldsNft","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"worldId","type":"uint256"},{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"enum NFTMarketRouterWorldsNftUserRoles.RoleAction","name":"roleAction","type":"uint8"}],"internalType":"struct NFTMarketRouterWorldsNftUserRoles.UserRoleAction[]","name":"userRoleActions","type":"tuple[]"}],"name":"manageWorldRolesForUsers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"worldOrExhibitionId","type":"uint256"},{"internalType":"uint256","name":"reservePrice","type":"uint256"},{"internalType":"uint256","name":"auctionDuration","type":"uint256"},{"internalType":"bool","name":"shouldSetBuyPrice","type":"bool"},{"internalType":"uint256","name":"buyPrice","type":"uint256"},{"internalType":"uint256","name":"saleStartsAt","type":"uint256"}],"name":"upsertListingV2","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61010060405234801562000011575f80fd5b50604051620032b4380380620032b4833981016040819052620000349162000121565b808383866001600160a01b0381163b62000061576040516348dc361f60e01b815260040160405180910390fd5b6001600160a01b0390811660805281163b62000090576040516307fa343360e41b815260040160405180910390fd5b6001600160a01b0390811660a05281163b620000bf576040516376d10ccd60e11b815260040160405180910390fd5b6001600160a01b0390811660c05281163b620000ee57604051631341312360e01b815260040160405180910390fd5b6001600160a01b031660e052506200017b92505050565b80516001600160a01b03811681146200011c575f80fd5b919050565b5f805f806080858703121562000135575f80fd5b620001408562000105565b9350620001506020860162000105565b9250620001606040860162000105565b9150620001706060860162000105565b905092959194509250565b60805160a05160c05160e051613041620002735f395f818161018b015281816114bc01528181611589015261165601525f818161023601528181610e5201528181610fa301528181611c2801528181611dbb01528181611ee301528181611fe1015261211f01525f818161012f01528181611aeb01528181611cd001528181611f8c01526120ca01525f81816101b10152818161078f015281816108320152818161090801528181610a6a01528181610b2601528181610ca60152818161119c015281816112f3015281816113ef0152818161172a015281816117fe015281816118bd015281816119630152611a4301526130415ff3fe608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80635599dfd711610093578063b590104e11610063578063b590104e14610234578063bfec346c1461025a578063cf2b5aa61461026d578063dbe3352a14610280575f80fd5b80635599dfd7146101e857806365c2cd91146101fb5780637e32d2411461020e5780637f9d22fe14610221575f80fd5b8063225cd1eb116100ce578063225cd1eb14610174578063228b131814610189578063331aaf9e146101af578063353ad881146101d5575f80fd5b80630a3ec799146100f45780631b39f9151461011a5780632059d9e21461012d575b5f80fd5b610107610102366004612399565b610293565b6040519081526020015b60405180910390f35b610107610128366004612428565b6102e9565b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610111565b6101876101823660046124ae565b6104cc565b005b7f000000000000000000000000000000000000000000000000000000000000000061014f565b7f000000000000000000000000000000000000000000000000000000000000000061014f565b6101876101e3366004612526565b610639565b61014f6101f63660046125b6565b610d82565b61014f61020936600461261a565b610ed3565b61018761021c366004612693565b611026565b61018761022f366004612740565b61104c565b7f000000000000000000000000000000000000000000000000000000000000000061014f565b61014f610268366004612790565b61105b565b61014f61027b3660046127e4565b6110d3565b61018761028e36600461285c565b611147565b5f6102a48a8a8a8a8a8a8a8a6102e9565b90505f5b888110156102db576102d38b8b8b848181106102c6576102c6612888565b9050602002013585611165565b6001016102a8565b509998505050505050505050565b5f868103610323576040517fa9d004a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215801561033057508115155b15610367576040517f1a8a2c1000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415610427576103928989895f81811061038357610383612888565b905060200201358888886112ae565b905082156103be576103be8989895f8181106103b0576103b0612888565b9050602002013588856113b5565b60015b87811015610421576103ee8a8a8a848181106103df576103df612888565b905060200201358989896112ae565b508315610419576104198a8a8a8481811061040b5761040b612888565b9050602002013589866113b5565b6001016103c1565b506104c0565b831561045f576040517fbf2c1df000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82610496576040517f75ce98b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b878110156104be576104b68a8a8a8481811061040b5761040b612888565b600101610498565b505b98975050505050505050565b5f819003610506576040517f589a99ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b81811015610633575f83838381811061052357610523612888565b905060400201602001602081019061053b91906128e2565b600281111561054c5761054c6128b5565b03610587576105828484848481811061056757610567612888565b61057d9260206040909202019081019150612900565b611490565b61062b565b600183838381811061059b5761059b612888565b90506040020160200160208101906105b391906128e2565b60028111156105c4576105c46128b5565b036105fa57610582848484848181106105df576105df612888565b6105f59260206040909202019081019150612900565b61155d565b61062b8484848481811061061057610610612888565b6106269260206040909202019081019150612900565b61162a565b600101610508565b50505050565b8215801561064657508115155b1561067d576040517f1a8a2c1000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015610689575084155b156106fd5785156106c5576040517e99fb3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80156106fd576040517f69a1d31600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415801561070a57508315155b15610741576040517fbf2c1df000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2ab2b52b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8981166004830152602482018990525f917f000000000000000000000000000000000000000000000000000000000000000090911690632ab2b52b90604401602060405180830381865afa1580156107d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107fa919061291b565b90505f81156108b8576040517f9e79b41f000000000000000000000000000000000000000000000000000000008152600481018390527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639e79b41f9060240161010060405180830381865afa15801561088d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b1919061293d565b60e0015190505b6040517f4635256e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152602482018b90525f9182917f00000000000000000000000000000000000000000000000000000000000000001690634635256e906044016040805180830381865afa15801561094c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109709190612a0a565b91509150825f148015610981575088155b80156109aa575073ffffffffffffffffffffffffffffffffffffffff82161580156109aa575086155b156109e1576040517f75ce98b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8883148015610a17575086158015610a0d575073ffffffffffffffffffffffffffffffffffffffff8216155b80610a1757508581145b15610bfd576040517f442559a200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d81166004830152602482018d90525f917f00000000000000000000000000000000000000000000000000000000000000009091169063442559a290604401602060405180830381865afa158015610ab1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad5919061291b565b6040517f7e04379500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8f81166004830152602482018f90529192505f917f00000000000000000000000000000000000000000000000000000000000000001690637e04379590604401602060405180830381865afa158015610b6b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b8f919061291b565b90505f8c8314610ba857610ba48f8f8f6116f7565b5060015b878214610bbe57610bba8f8f8a6117cb565b5060015b80610bf5576040517f41deec4500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050610d74565b8815610c2f578215610c2057888314610c1b57610c1b848b8b61189f565b610c2f565b610c2d8c8c8c8c8c6112ae565b505b8615610c4857858114610c4857610c488c8c8c896113b5565b8680610c5357508815155b15610d27576040517f7e04379500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d81166004830152602482018d90525f917f000000000000000000000000000000000000000000000000000000000000000090911690637e04379590604401602060405180830381865afa158015610ced573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d11919061291b565b9050858114610d2557610d258d8d886117cb565b505b88158015610d3457508215155b15610d4257610d428461195e565b86158015610d65575073ffffffffffffffffffffffffffffffffffffffff821615155b15610d7457610d748c8c611a17565b505050505050505050505050565b5f818015801590610d975750610d9781421190565b15610dce576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83608001355f03610e0b576040517fa87860d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608401355f819003610e1b5750425b610e89610e288780612a36565b610e3560208a018a612a36565b610e4260408c018c612a36565b610e5060808d013589612a97565b7f00000000000000000000000000000000000000000000000000000000000000008e6060016020810190610e849190612ad5565b611ae4565b92505f6040518060800160405280875f01358152602001876020013581526020018760400135815260200187606001358152509050610ec984825f611bce565b5050509392505050565b5f818015801590610ee85750610ee881421190565b15610f1f576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83608001355f03610f5c576040517fa87860d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608401355f819003610f6c5750425b610fdb610f798880612a36565b610f8660208b018b612a36565b610f9360408d018d612a36565b610fa160808d013589612a97565b7f00000000000000000000000000000000000000000000000000000000000000008f6060016020810190610fd59190612ad5565b8f611cc9565b92505f6040518060800160405280875f0135815260200187602001358152602001876040013581526020018760600135815250905061101b84825f611bce565b505050949350505050565b6110438761103936899003890189612b00565b8787878787611db6565b50505050505050565b61104387878787878787611e94565b5f818015801590611070575061107081421190565b156110a7576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110b085611f85565b91506110cb826110c536879003870187612b00565b5f611bce565b509392505050565b5f8180158015906110e857506110e881421190565b1561111f576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112986866120c3565b915061113e826110c536879003870187612b00565b50949350505050565b6111608361115a36859003850185612b00565b83611bce565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff8416602482015260448101839052606481018290525f90819061123d907f000000000000000000000000000000000000000000000000000000000000000090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4eb1231700000000000000000000000000000000000000000000000000000000179052339190612207565b915091508115801561129957507fe5c3f2630000000000000000000000000000000000000000000000000000000061127482612b89565b7fffffffff000000000000000000000000000000000000000000000000000000001614155b156112a7576112a7816122b7565b5050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8616602482015260448101859052606481018490526084810183905260a481018290525f908190611394907f00000000000000000000000000000000000000000000000000000000000000009060c401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8098531d000000000000000000000000000000000000000000000000000000001790523391906122fc565b9050808060200190518101906113aa919061291b565b979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff851660248201526044810184905260648101839052608481018290526112a7907f00000000000000000000000000000000000000000000000000000000000000009060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2fbbb25a000000000000000000000000000000000000000000000000000000001790523391906122fc565b6040516024810183905273ffffffffffffffffffffffffffffffffffffffff82166044820152611160907f000000000000000000000000000000000000000000000000000000000000000090606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f05d8d4f2000000000000000000000000000000000000000000000000000000001790523391906122fc565b6040516024810183905273ffffffffffffffffffffffffffffffffffffffff82166044820152611160907f000000000000000000000000000000000000000000000000000000000000000090606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095f0c70000000000000000000000000000000000000000000000000000000001790523391906122fc565b6040516024810183905273ffffffffffffffffffffffffffffffffffffffff82166044820152611160907f000000000000000000000000000000000000000000000000000000000000000090606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f691aa51a000000000000000000000000000000000000000000000000000000001790523391906122fc565b60405173ffffffffffffffffffffffffffffffffffffffff841660248201526044810183905260648101829052610633907f000000000000000000000000000000000000000000000000000000000000000090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f574c8229000000000000000000000000000000000000000000000000000000001790523391906122fc565b60405173ffffffffffffffffffffffffffffffffffffffff841660248201526044810183905260648101829052610633907f000000000000000000000000000000000000000000000000000000000000000090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4eb12317000000000000000000000000000000000000000000000000000000001790523391906122fc565b604051602481018490526044810183905260648101829052610633907f000000000000000000000000000000000000000000000000000000000000000090608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe2cf968b000000000000000000000000000000000000000000000000000000001790523391906122fc565b611a137f00000000000000000000000000000000000000000000000000000000000000008260405160240161199591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f21506fff000000000000000000000000000000000000000000000000000000001790523391906122fc565b5050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052611160907f000000000000000000000000000000000000000000000000000000000000000090606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f21561935000000000000000000000000000000000000000000000000000000001790523391906122fc565b5f80611ba97f00000000000000000000000000000000000000000000000000000000000000008c8c8c8c8c8c8c8c8c604051602401611b2b99989796959493929190612c1f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f189267b2000000000000000000000000000000000000000000000000000000001790523391906122fc565b905080806020019051810190611bbf9190612ca0565b9b9a5050505050505050505050565b815160208301516040808501516060860151915173ffffffffffffffffffffffffffffffffffffffff8816602482015260448101949094526064840192909252608483019190915260a482015260c48101829052610633907f00000000000000000000000000000000000000000000000000000000000000009060e401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f42017634000000000000000000000000000000000000000000000000000000001790523391906122fc565b5f80611d907f00000000000000000000000000000000000000000000000000000000000000008d8d8d8d8d8d8d8d8d8d604051602401611d129a99989796959493929190612d5c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa973d0e8000000000000000000000000000000000000000000000000000000001790523391906122fc565b905080806020019051810190611da69190612ca0565b9c9b505050505050505050505050565b611e8a7f000000000000000000000000000000000000000000000000000000000000000088885f015189602001518a604001518b606001518b8b8b8b8b604051602401611e0c9a99989796959493929190612df2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f9901261c000000000000000000000000000000000000000000000000000000001790523391906122fc565b5050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8816602482015260448101879052606481018690526084810185905260a4810184905260c4810183905260e48101829052611e8a907f00000000000000000000000000000000000000000000000000000000000000009061010401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f7f9d22fe000000000000000000000000000000000000000000000000000000001790523391906122fc565b5f806120a67f0000000000000000000000000000000000000000000000000000000000000000611fb58580612a36565b611fc26020880188612a36565b611fcf60408a018a612a36565b611fdf60808c0160608d01612e5f565b7f000000000000000000000000000000000000000000000000000000000000000061201060a08e0160808f01612ad5565b60405160240161202899989796959493929190612e82565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd061a9f2000000000000000000000000000000000000000000000000000000001790523391906122fc565b9050808060200190518101906120bc9190612ca0565b9392505050565b5f806121e97f00000000000000000000000000000000000000000000000000000000000000006120f38680612a36565b6121006020890189612a36565b61210d60408b018b612a36565b61211d60808d0160608e01612e5f565b7f00000000000000000000000000000000000000000000000000000000000000008d60800160208101906121519190612ad5565b8d60405160240161216b9a99989796959493929190612f09565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f57848031000000000000000000000000000000000000000000000000000000001790523391906122fc565b9050808060200190518101906121ff9190612ca0565b949350505050565b5f60608373ffffffffffffffffffffffffffffffffffffffff168386604051602001612234929190612fc1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261226c91613000565b5f604051808303815f865af19150503d805f81146122a5576040519150601f19603f3d011682016040523d82523d5f602084013e6122aa565b606091505b5090969095509350505050565b8051156122c75780518082602001fd5b6040517f3cfe059f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60605f61230a858585612207565b92509050806110cb576110cb826122b7565b73ffffffffffffffffffffffffffffffffffffffff811681146122f9575f80fd5b5f8083601f84011261234d575f80fd5b50813567ffffffffffffffff811115612364575f80fd5b6020830191508360208260051b850101111561237e575f80fd5b9250929050565b80358015158114612394575f80fd5b919050565b5f805f805f805f805f6101008a8c0312156123b2575f80fd5b89356123bd8161231c565b985060208a013567ffffffffffffffff8111156123d8575f80fd5b6123e48c828d0161233d565b90995097505060408a0135955060608a0135945060808a0135935061240b60a08b01612385565b925060c08a0135915060e08a013590509295985092959850929598565b5f805f805f805f8060e0898b03121561243f575f80fd5b883561244a8161231c565b9750602089013567ffffffffffffffff811115612465575f80fd5b6124718b828c0161233d565b90985096505060408901359450606089013593506080890135925061249860a08a01612385565b915060c089013590509295985092959890939650565b5f805f604084860312156124c0575f80fd5b83359250602084013567ffffffffffffffff808211156124de575f80fd5b818601915086601f8301126124f1575f80fd5b8135818111156124ff575f80fd5b8760208260061b8501011115612513575f80fd5b6020830194508093505050509250925092565b5f805f805f805f80610100898b03121561253e575f80fd5b88356125498161231c565b97506020890135965060408901359550606089013594506080890135935061257360a08a01612385565b925060c0890135915060e089013590509295985092959890939650565b5f608082840312156125a0575f80fd5b50919050565b5f60a082840312156125a0575f80fd5b5f805f60e084860312156125c8575f80fd5b833567ffffffffffffffff8111156125de575f80fd5b6125ea86828701612590565b9350506125fa85602086016125a6565b915060c084013590509250925092565b5f604082840312156125a0575f80fd5b5f805f80610100858703121561262e575f80fd5b843567ffffffffffffffff80821115612645575f80fd5b61265188838901612590565b95506020870135915080821115612666575f80fd5b506126738782880161260a565b93505061268386604087016125a6565b9396929550929360e00135925050565b5f805f805f805f610120888a0312156126aa575f80fd5b87356126b58161231c565b96506126c48960208a01612590565b955060a0880135945060c0880135935060e088013567ffffffffffffffff808211156126ee575f80fd5b818a0191508a601f830112612701575f80fd5b81358181111561270f575f80fd5b8b6020828501011115612720575f80fd5b602083019550809450505050610100880135905092959891949750929550565b5f805f805f805f60e0888a031215612756575f80fd5b87356127618161231c565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b5f805f60c084860312156127a2575f80fd5b833567ffffffffffffffff8111156127b8575f80fd5b6127c4868287016125a6565b9350506127d48560208601612590565b915060a084013590509250925092565b5f805f8060e085870312156127f7575f80fd5b843567ffffffffffffffff8082111561280e575f80fd5b61281a888389016125a6565b9550602087013591508082111561282f575f80fd5b5061283c8782880161260a565b93505061284c8660408701612590565b9396929550929360c00135925050565b5f805f60c0848603121561286e575f80fd5b83356128798161231c565b92506127d48560208601612590565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f602082840312156128f2575f80fd5b8135600381106120bc575f80fd5b5f60208284031215612910575f80fd5b81356120bc8161231c565b5f6020828403121561292b575f80fd5b5051919050565b80516123948161231c565b5f61010080838503121561294f575f80fd5b6040519081019067ffffffffffffffff82118183101715612997577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b81604052835191506129a88261231c565b818152602084015160208201526129c160408501612932565b6040820152606084015160608201526080840151608082015260a084015160a08201526129f060c08501612932565b60c082015260e084015160e0820152809250505092915050565b5f8060408385031215612a1b575f80fd5b8251612a268161231c565b6020939093015192949293505050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a69575f80fd5b83018035915067ffffffffffffffff821115612a83575f80fd5b60200191503681900382131561237e575f80fd5b80820180821115612acf577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b92915050565b5f60208284031215612ae5575f80fd5b81356bffffffffffffffffffffffff811681146120bc575f80fd5b5f60808284031215612b10575f80fd5b6040516080810181811067ffffffffffffffff82111715612b58577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b5f815160208301517fffffffff0000000000000000000000000000000000000000000000000000000080821693506004831015612bd05780818460040360031b1b83161693505b505050919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60c081525f612c3260c083018b8d612bd8565b8281036020840152612c45818a8c612bd8565b90508281036040840152612c5a81888a612bd8565b6060840196909652505073ffffffffffffffffffffffffffffffffffffffff9290921660808301526bffffffffffffffffffffffff1660a0909101529695505050505050565b5f60208284031215612cb0575f80fd5b81516120bc8161231c565b5f8135612cc78161231c565b73ffffffffffffffffffffffffffffffffffffffff1683526020820135368390037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1018112612d14575f80fd5b820160208101903567ffffffffffffffff811115612d30575f80fd5b803603821315612d3e575f80fd5b60406020860152612d53604086018284612bd8565b95945050505050565b60e081525f612d6f60e083018c8e612bd8565b8281036020840152612d82818b8d612bd8565b90508281036040840152612d9781898b612bd8565b905086606084015273ffffffffffffffffffffffffffffffffffffffff861660808401526bffffffffffffffffffffffff851660a084015282810360c0840152612de18185612cbb565b9d9c50505050505050505050505050565b5f61012073ffffffffffffffffffffffffffffffffffffffff8d1683528b60208401528a60408401528960608401528860808401528760a08401528660c08401528060e0840152612e468184018688612bd8565b915050826101008301529b9a5050505050505050505050565b5f60208284031215612e6f575f80fd5b813563ffffffff811681146120bc575f80fd5b60c081525f612e9560c083018b8d612bd8565b8281036020840152612ea8818a8c612bd8565b90508281036040840152612ebd81888a612bd8565b63ffffffff969096166060840152505073ffffffffffffffffffffffffffffffffffffffff9290921660808301526bffffffffffffffffffffffff1660a0909101529695505050505050565b60e081525f612f1c60e083018c8e612bd8565b8281036020840152612f2f818b8d612bd8565b90508281036040840152612f4481898b612bd8565b905063ffffffff8716606084015273ffffffffffffffffffffffffffffffffffffffff861660808401526bffffffffffffffffffffffff851660a084015282810360c0840152612de18185612cbb565b5f81515f5b81811015612fb35760208185018101518683015201612f99565b505f93019283525090919050565b5f612fcc8285612f94565b60609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001683525050601401919050565b5f6120bc8284612f9456fea2646970667358221220c4fc62ae071123245e22df482fd4745ad2d5a61e292e60ca558281668c58461964736f6c63430008170033000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e00000000000000000000000069525dac489e4718964b5615c3d794a25d62beb7
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106100f0575f3560e01c80635599dfd711610093578063b590104e11610063578063b590104e14610234578063bfec346c1461025a578063cf2b5aa61461026d578063dbe3352a14610280575f80fd5b80635599dfd7146101e857806365c2cd91146101fb5780637e32d2411461020e5780637f9d22fe14610221575f80fd5b8063225cd1eb116100ce578063225cd1eb14610174578063228b131814610189578063331aaf9e146101af578063353ad881146101d5575f80fd5b80630a3ec799146100f45780631b39f9151461011a5780632059d9e21461012d575b5f80fd5b610107610102366004612399565b610293565b6040519081526020015b60405180910390f35b610107610128366004612428565b6102e9565b7f000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e5b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610111565b6101876101823660046124ae565b6104cc565b005b7f00000000000000000000000069525dac489e4718964b5615c3d794a25d62beb761014f565b7f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f61014f565b6101876101e3366004612526565b610639565b61014f6101f63660046125b6565b610d82565b61014f61020936600461261a565b610ed3565b61018761021c366004612693565b611026565b61018761022f366004612740565b61104c565b7f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a61014f565b61014f610268366004612790565b61105b565b61014f61027b3660046127e4565b6110d3565b61018761028e36600461285c565b611147565b5f6102a48a8a8a8a8a8a8a8a6102e9565b90505f5b888110156102db576102d38b8b8b848181106102c6576102c6612888565b9050602002013585611165565b6001016102a8565b509998505050505050505050565b5f868103610323576040517fa9d004a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215801561033057508115155b15610367576040517f1a8a2c1000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415610427576103928989895f81811061038357610383612888565b905060200201358888886112ae565b905082156103be576103be8989895f8181106103b0576103b0612888565b9050602002013588856113b5565b60015b87811015610421576103ee8a8a8a848181106103df576103df612888565b905060200201358989896112ae565b508315610419576104198a8a8a8481811061040b5761040b612888565b9050602002013589866113b5565b6001016103c1565b506104c0565b831561045f576040517fbf2c1df000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82610496576040517f75ce98b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b878110156104be576104b68a8a8a8481811061040b5761040b612888565b600101610498565b505b98975050505050505050565b5f819003610506576040517f589a99ea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b81811015610633575f83838381811061052357610523612888565b905060400201602001602081019061053b91906128e2565b600281111561054c5761054c6128b5565b03610587576105828484848481811061056757610567612888565b61057d9260206040909202019081019150612900565b611490565b61062b565b600183838381811061059b5761059b612888565b90506040020160200160208101906105b391906128e2565b60028111156105c4576105c46128b5565b036105fa57610582848484848181106105df576105df612888565b6105f59260206040909202019081019150612900565b61155d565b61062b8484848481811061061057610610612888565b6106269260206040909202019081019150612900565b61162a565b600101610508565b50505050565b8215801561064657508115155b1561067d576040517f1a8a2c1000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015610689575084155b156106fd5785156106c5576040517e99fb3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80156106fd576040517f69a1d31600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415801561070a57508315155b15610741576040517fbf2c1df000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f2ab2b52b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8981166004830152602482018990525f917f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f90911690632ab2b52b90604401602060405180830381865afa1580156107d6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107fa919061291b565b90505f81156108b8576040517f9e79b41f000000000000000000000000000000000000000000000000000000008152600481018390527f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f73ffffffffffffffffffffffffffffffffffffffff1690639e79b41f9060240161010060405180830381865afa15801561088d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b1919061293d565b60e0015190505b6040517f4635256e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152602482018b90525f9182917f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f1690634635256e906044016040805180830381865afa15801561094c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109709190612a0a565b91509150825f148015610981575088155b80156109aa575073ffffffffffffffffffffffffffffffffffffffff82161580156109aa575086155b156109e1576040517f75ce98b600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8883148015610a17575086158015610a0d575073ffffffffffffffffffffffffffffffffffffffff8216155b80610a1757508581145b15610bfd576040517f442559a200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d81166004830152602482018d90525f917f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f9091169063442559a290604401602060405180830381865afa158015610ab1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad5919061291b565b6040517f7e04379500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8f81166004830152602482018f90529192505f917f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f1690637e04379590604401602060405180830381865afa158015610b6b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b8f919061291b565b90505f8c8314610ba857610ba48f8f8f6116f7565b5060015b878214610bbe57610bba8f8f8a6117cb565b5060015b80610bf5576040517f41deec4500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050610d74565b8815610c2f578215610c2057888314610c1b57610c1b848b8b61189f565b610c2f565b610c2d8c8c8c8c8c6112ae565b505b8615610c4857858114610c4857610c488c8c8c896113b5565b8680610c5357508815155b15610d27576040517f7e04379500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d81166004830152602482018d90525f917f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f90911690637e04379590604401602060405180830381865afa158015610ced573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d11919061291b565b9050858114610d2557610d258d8d886117cb565b505b88158015610d3457508215155b15610d4257610d428461195e565b86158015610d65575073ffffffffffffffffffffffffffffffffffffffff821615155b15610d7457610d748c8c611a17565b505050505050505050505050565b5f818015801590610d975750610d9781421190565b15610dce576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83608001355f03610e0b576040517fa87860d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608401355f819003610e1b5750425b610e89610e288780612a36565b610e3560208a018a612a36565b610e4260408c018c612a36565b610e5060808d013589612a97565b7f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a8e6060016020810190610e849190612ad5565b611ae4565b92505f6040518060800160405280875f01358152602001876020013581526020018760400135815260200187606001358152509050610ec984825f611bce565b5050509392505050565b5f818015801590610ee85750610ee881421190565b15610f1f576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83608001355f03610f5c576040517fa87860d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608401355f819003610f6c5750425b610fdb610f798880612a36565b610f8660208b018b612a36565b610f9360408d018d612a36565b610fa160808d013589612a97565b7f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a8f6060016020810190610fd59190612ad5565b8f611cc9565b92505f6040518060800160405280875f0135815260200187602001358152602001876040013581526020018760600135815250905061101b84825f611bce565b505050949350505050565b6110438761103936899003890189612b00565b8787878787611db6565b50505050505050565b61104387878787878787611e94565b5f818015801590611070575061107081421190565b156110a7576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6110b085611f85565b91506110cb826110c536879003870187612b00565b5f611bce565b509392505050565b5f8180158015906110e857506110e881421190565b1561111f576040517fbcb9700400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61112986866120c3565b915061113e826110c536879003870187612b00565b50949350505050565b6111608361115a36859003850185612b00565b83611bce565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff8416602482015260448101839052606481018290525f90819061123d907f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f90608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4eb1231700000000000000000000000000000000000000000000000000000000179052339190612207565b915091508115801561129957507fe5c3f2630000000000000000000000000000000000000000000000000000000061127482612b89565b7fffffffff000000000000000000000000000000000000000000000000000000001614155b156112a7576112a7816122b7565b5050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8616602482015260448101859052606481018490526084810183905260a481018290525f908190611394907f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f9060c401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8098531d000000000000000000000000000000000000000000000000000000001790523391906122fc565b9050808060200190518101906113aa919061291b565b979650505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff851660248201526044810184905260648101839052608481018290526112a7907f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f9060a401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2fbbb25a000000000000000000000000000000000000000000000000000000001790523391906122fc565b6040516024810183905273ffffffffffffffffffffffffffffffffffffffff82166044820152611160907f00000000000000000000000069525dac489e4718964b5615c3d794a25d62beb790606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f05d8d4f2000000000000000000000000000000000000000000000000000000001790523391906122fc565b6040516024810183905273ffffffffffffffffffffffffffffffffffffffff82166044820152611160907f00000000000000000000000069525dac489e4718964b5615c3d794a25d62beb790606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095f0c70000000000000000000000000000000000000000000000000000000001790523391906122fc565b6040516024810183905273ffffffffffffffffffffffffffffffffffffffff82166044820152611160907f00000000000000000000000069525dac489e4718964b5615c3d794a25d62beb790606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f691aa51a000000000000000000000000000000000000000000000000000000001790523391906122fc565b60405173ffffffffffffffffffffffffffffffffffffffff841660248201526044810183905260648101829052610633907f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f90608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f574c8229000000000000000000000000000000000000000000000000000000001790523391906122fc565b60405173ffffffffffffffffffffffffffffffffffffffff841660248201526044810183905260648101829052610633907f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f90608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4eb12317000000000000000000000000000000000000000000000000000000001790523391906122fc565b604051602481018490526044810183905260648101829052610633907f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f90608401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fe2cf968b000000000000000000000000000000000000000000000000000000001790523391906122fc565b611a137f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f8260405160240161199591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f21506fff000000000000000000000000000000000000000000000000000000001790523391906122fc565b5050565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052611160907f000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f90606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f21561935000000000000000000000000000000000000000000000000000000001790523391906122fc565b5f80611ba97f000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e8c8c8c8c8c8c8c8c8c604051602401611b2b99989796959493929190612c1f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f189267b2000000000000000000000000000000000000000000000000000000001790523391906122fc565b905080806020019051810190611bbf9190612ca0565b9b9a5050505050505050505050565b815160208301516040808501516060860151915173ffffffffffffffffffffffffffffffffffffffff8816602482015260448101949094526064840192909252608483019190915260a482015260c48101829052610633907f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a9060e401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f42017634000000000000000000000000000000000000000000000000000000001790523391906122fc565b5f80611d907f000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e8d8d8d8d8d8d8d8d8d8d604051602401611d129a99989796959493929190612d5c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa973d0e8000000000000000000000000000000000000000000000000000000001790523391906122fc565b905080806020019051810190611da69190612ca0565b9c9b505050505050505050505050565b611e8a7f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a88885f015189602001518a604001518b606001518b8b8b8b8b604051602401611e0c9a99989796959493929190612df2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f9901261c000000000000000000000000000000000000000000000000000000001790523391906122fc565b5050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff8816602482015260448101879052606481018690526084810185905260a4810184905260c4810183905260e48101829052611e8a907f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a9061010401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f7f9d22fe000000000000000000000000000000000000000000000000000000001790523391906122fc565b5f806120a67f000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e611fb58580612a36565b611fc26020880188612a36565b611fcf60408a018a612a36565b611fdf60808c0160608d01612e5f565b7f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a61201060a08e0160808f01612ad5565b60405160240161202899989796959493929190612e82565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd061a9f2000000000000000000000000000000000000000000000000000000001790523391906122fc565b9050808060200190518101906120bc9190612ca0565b9392505050565b5f806121e97f000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e6120f38680612a36565b6121006020890189612a36565b61210d60408b018b612a36565b61211d60808d0160608e01612e5f565b7f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a8d60800160208101906121519190612ad5565b8d60405160240161216b9a99989796959493929190612f09565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f57848031000000000000000000000000000000000000000000000000000000001790523391906122fc565b9050808060200190518101906121ff9190612ca0565b949350505050565b5f60608373ffffffffffffffffffffffffffffffffffffffff168386604051602001612234929190612fc1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261226c91613000565b5f604051808303815f865af19150503d805f81146122a5576040519150601f19603f3d011682016040523d82523d5f602084013e6122aa565b606091505b5090969095509350505050565b8051156122c75780518082602001fd5b6040517f3cfe059f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b60605f61230a858585612207565b92509050806110cb576110cb826122b7565b73ffffffffffffffffffffffffffffffffffffffff811681146122f9575f80fd5b5f8083601f84011261234d575f80fd5b50813567ffffffffffffffff811115612364575f80fd5b6020830191508360208260051b850101111561237e575f80fd5b9250929050565b80358015158114612394575f80fd5b919050565b5f805f805f805f805f6101008a8c0312156123b2575f80fd5b89356123bd8161231c565b985060208a013567ffffffffffffffff8111156123d8575f80fd5b6123e48c828d0161233d565b90995097505060408a0135955060608a0135945060808a0135935061240b60a08b01612385565b925060c08a0135915060e08a013590509295985092959850929598565b5f805f805f805f8060e0898b03121561243f575f80fd5b883561244a8161231c565b9750602089013567ffffffffffffffff811115612465575f80fd5b6124718b828c0161233d565b90985096505060408901359450606089013593506080890135925061249860a08a01612385565b915060c089013590509295985092959890939650565b5f805f604084860312156124c0575f80fd5b83359250602084013567ffffffffffffffff808211156124de575f80fd5b818601915086601f8301126124f1575f80fd5b8135818111156124ff575f80fd5b8760208260061b8501011115612513575f80fd5b6020830194508093505050509250925092565b5f805f805f805f80610100898b03121561253e575f80fd5b88356125498161231c565b97506020890135965060408901359550606089013594506080890135935061257360a08a01612385565b925060c0890135915060e089013590509295985092959890939650565b5f608082840312156125a0575f80fd5b50919050565b5f60a082840312156125a0575f80fd5b5f805f60e084860312156125c8575f80fd5b833567ffffffffffffffff8111156125de575f80fd5b6125ea86828701612590565b9350506125fa85602086016125a6565b915060c084013590509250925092565b5f604082840312156125a0575f80fd5b5f805f80610100858703121561262e575f80fd5b843567ffffffffffffffff80821115612645575f80fd5b61265188838901612590565b95506020870135915080821115612666575f80fd5b506126738782880161260a565b93505061268386604087016125a6565b9396929550929360e00135925050565b5f805f805f805f610120888a0312156126aa575f80fd5b87356126b58161231c565b96506126c48960208a01612590565b955060a0880135945060c0880135935060e088013567ffffffffffffffff808211156126ee575f80fd5b818a0191508a601f830112612701575f80fd5b81358181111561270f575f80fd5b8b6020828501011115612720575f80fd5b602083019550809450505050610100880135905092959891949750929550565b5f805f805f805f60e0888a031215612756575f80fd5b87356127618161231c565b9960208901359950604089013598606081013598506080810135975060a0810135965060c00135945092505050565b5f805f60c084860312156127a2575f80fd5b833567ffffffffffffffff8111156127b8575f80fd5b6127c4868287016125a6565b9350506127d48560208601612590565b915060a084013590509250925092565b5f805f8060e085870312156127f7575f80fd5b843567ffffffffffffffff8082111561280e575f80fd5b61281a888389016125a6565b9550602087013591508082111561282f575f80fd5b5061283c8782880161260a565b93505061284c8660408701612590565b9396929550929360c00135925050565b5f805f60c0848603121561286e575f80fd5b83356128798161231c565b92506127d48560208601612590565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f602082840312156128f2575f80fd5b8135600381106120bc575f80fd5b5f60208284031215612910575f80fd5b81356120bc8161231c565b5f6020828403121561292b575f80fd5b5051919050565b80516123948161231c565b5f61010080838503121561294f575f80fd5b6040519081019067ffffffffffffffff82118183101715612997577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b81604052835191506129a88261231c565b818152602084015160208201526129c160408501612932565b6040820152606084015160608201526080840151608082015260a084015160a08201526129f060c08501612932565b60c082015260e084015160e0820152809250505092915050565b5f8060408385031215612a1b575f80fd5b8251612a268161231c565b6020939093015192949293505050565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a69575f80fd5b83018035915067ffffffffffffffff821115612a83575f80fd5b60200191503681900382131561237e575f80fd5b80820180821115612acf577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b92915050565b5f60208284031215612ae5575f80fd5b81356bffffffffffffffffffffffff811681146120bc575f80fd5b5f60808284031215612b10575f80fd5b6040516080810181811067ffffffffffffffff82111715612b58577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b8060405250823581526020830135602082015260408301356040820152606083013560608201528091505092915050565b5f815160208301517fffffffff0000000000000000000000000000000000000000000000000000000080821693506004831015612bd05780818460040360031b1b83161693505b505050919050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60c081525f612c3260c083018b8d612bd8565b8281036020840152612c45818a8c612bd8565b90508281036040840152612c5a81888a612bd8565b6060840196909652505073ffffffffffffffffffffffffffffffffffffffff9290921660808301526bffffffffffffffffffffffff1660a0909101529695505050505050565b5f60208284031215612cb0575f80fd5b81516120bc8161231c565b5f8135612cc78161231c565b73ffffffffffffffffffffffffffffffffffffffff1683526020820135368390037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1018112612d14575f80fd5b820160208101903567ffffffffffffffff811115612d30575f80fd5b803603821315612d3e575f80fd5b60406020860152612d53604086018284612bd8565b95945050505050565b60e081525f612d6f60e083018c8e612bd8565b8281036020840152612d82818b8d612bd8565b90508281036040840152612d9781898b612bd8565b905086606084015273ffffffffffffffffffffffffffffffffffffffff861660808401526bffffffffffffffffffffffff851660a084015282810360c0840152612de18185612cbb565b9d9c50505050505050505050505050565b5f61012073ffffffffffffffffffffffffffffffffffffffff8d1683528b60208401528a60408401528960608401528860808401528760a08401528660c08401528060e0840152612e468184018688612bd8565b915050826101008301529b9a5050505050505050505050565b5f60208284031215612e6f575f80fd5b813563ffffffff811681146120bc575f80fd5b60c081525f612e9560c083018b8d612bd8565b8281036020840152612ea8818a8c612bd8565b90508281036040840152612ebd81888a612bd8565b63ffffffff969096166060840152505073ffffffffffffffffffffffffffffffffffffffff9290921660808301526bffffffffffffffffffffffff1660a0909101529695505050505050565b60e081525f612f1c60e083018c8e612bd8565b8281036020840152612f2f818b8d612bd8565b90508281036040840152612f4481898b612bd8565b905063ffffffff8716606084015273ffffffffffffffffffffffffffffffffffffffff861660808401526bffffffffffffffffffffffff851660a084015282810360c0840152612de18185612cbb565b5f81515f5b81811015612fb35760208185018101518683015201612f99565b505f93019283525090919050565b5f612fcc8285612f94565b60609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001683525050601401919050565b5f6120bc8284612f9456fea2646970667358221220c4fc62ae071123245e22df482fd4745ad2d5a61e292e60ca558281668c58461964736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e00000000000000000000000069525dac489e4718964b5615c3d794a25d62beb7
-----Decoded View---------------
Arg [0] : _nftMarket (address): 0xcDA72070E455bb31C7690a170224Ce43623d0B6f
Arg [1] : _nftDropMarket (address): 0x53F451165Ba6fdbe39A134673d13948261B2334A
Arg [2] : _nftCollectionFactory (address): 0x612E2DadDc89d91409e40f946f9f7CfE422e777E
Arg [3] : _worlds (address): 0x69525Dac489e4718964B5615c3D794a25d62bEb7
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000cda72070e455bb31c7690a170224ce43623d0b6f
Arg [1] : 00000000000000000000000053f451165ba6fdbe39a134673d13948261b2334a
Arg [2] : 000000000000000000000000612e2daddc89d91409e40f946f9f7cfe422e777e
Arg [3] : 00000000000000000000000069525dac489e4718964b5615c3d794a25d62beb7
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.