ERC-1155
Overview
Max Total Supply
0 GKAM
Holders
133
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
MorningsOpenEditions
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; import "./ERC1155Base.sol"; /** * @author Fount Gallery * @title Mornings Open Editions by Gutty Kreum * @notice Mornings is a collection of digital memories exploring morning ambience by pixel artist, Gutty Kreum. * A limited release in collaboration with Fount Gallery, Mornings drops on June 22, 2023. * * Features: * - Open edition NFTs * - ERC-1155 lazy minting * - Flexible minting conditions with EIP-712 signatures or on-chain Fount Card checks * - Swappable metadata contract * - On-chain royalties standard (EIP-2981) * - Support for OpenSea's Operator Filterer to allow royalties */ contract MorningsOpenEditions is ERC1155Base { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @dev Stores information about a given token struct TokenData { uint128 price; uint32 startTime; uint32 endTime; uint256 gutty_reserve_collected; uint256 fount_reserve_collected; uint16 perAddressAllowance; bool fountExclusive; bool requiresSig; } /// @dev Mapping of token id to token data mapping(uint256 => TokenData) internal _idToTokenData; /// @dev Check if the artist has minted the batch of 25 prior to launch bool public _artistBatchMinted = false; /// @notice The amount of tokens reserved for Fount Gallery Patrons uint256 public constant FOUNT_PATRON_RESERVE = 100; /// @notice The amount of tokens reserved for Gutty Kreum artwork holders uint256 public constant GUTTY_KREUM_RESERVE = 225; /* ------------------------------------------------------------------------ M O D I F I E R S ------------------------------------------------------------------------ */ /** * @dev Reverts if the caller is not the artist */ modifier onlyArtist() { require(msg.sender == artist, "Only the artist can call this function"); _; } /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ /** TOKEN DATA ---------------------------------------------------------- */ error TokenDataDoesNotExist(); error TokenDataAlreadyExists(); error CannotSetStartTimeToZero(); error CannotSetEndTimeToThePast(); /** SALE CONDITIONS ---------------------------------------------------- */ error RequiresFountCard(); error RequiresSignature(); error InvalidSignature(); error SoldOut(); error BatchAlreadyMinted(); /** PURCHASING --------------------------------------------------------- */ error NotForSale(); error IncorrectPaymentAmount(); error AmountExceedsMaxWalletMint(); error AmountExceedsWalletAllowance(); /** EDITIONS ----------------------------------------------------------- */ error OpenEditionEnded(); error OpenEditionNotStartedYet(); /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ event TokenDataAdded(uint256 indexed id, TokenData tokenData); event TokenDataSaleTimesUpdated(uint256 indexed id, TokenData tokenData); event TokenDataSalePriceUpdated(uint256 indexed id, TokenData tokenData); event TokenDataSaleConditionsUpdated(uint256 indexed id, TokenData tokenData); event CollectedOpenEdition(uint256 indexed id); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param owner_ The owner of the contract * @param admin_ The admin of the contract * @param payments_ The address where payments should be sent * @param royaltiesAmount_ The royalty percentage with two decimals (10,000 = 100%) * @param metadata_ The initial metadata contract address * @param fountCard_ The address of the Fount Gallery Patron Card */ constructor( address owner_, address admin_, address payments_, uint256 royaltiesAmount_, address metadata_, address fountCard_ ) ERC1155Base(owner_, admin_, payments_, royaltiesAmount_, metadata_, fountCard_) {} /* ------------------------------------------------------------------------ O P E N E D I T I O N S ------------------------------------------------------------------------ */ /** * @notice Mints a batch of 25 editions to the artist's wallet * * Reverts if: * - the batch has already been minted */ function mintArtistBatch() external onlyArtist { if (_artistBatchMinted) revert BatchAlreadyMinted(); TokenData memory tokenData = _idToTokenData[3]; tokenData.gutty_reserve_collected += 25; _idToTokenData[3] = tokenData; _artistBatchMinted = true; _mintToArtistFirst(artist, 3, 25); emit CollectedOpenEdition(3); } /** * @notice Mints a number of editions from an open edition NFT * @dev Calls internal `_collectEdition` for logic. * * Reverts if: * - the edition requires an off-chain signature * - see `_collectEdition` for other conditions * * @param id The id of the edition * @param amount_guttys The amount of editions to mint from the Gutty Kreum reserve * @param amount_founts The amount of editions to mint from the Fount Gallery Patron Card reserve * @param to The address to mint the token to */ function collectEdition( uint256 id, uint256 amount_guttys, uint256 amount_founts, address to ) external payable { TokenData memory tokenData = _idToTokenData[id]; if (tokenData.requiresSig) revert RequiresSignature(); _collectEdition(id, amount_guttys, amount_founts, to, tokenData); } /** * @notice Mints a number of editions from an open edition NFT with an off-chain signature * @dev Calls internal `_collectEdition` for logic. * * Reverts if: * - the edition requires an off-chain signature and the signature is invalid * - see `_collectEdition` for other conditions * * @param id The id of the edition * @param amount_guttys The amount of editions to mint from the Gutty Kreum reserve * @param amount_founts The amount of editions to mint from the Fount Gallery Patron Card reserve * @param to The address to mint the token to * @param signature The off-chain signature which permits a mint */ function collectEdition( uint256 id, uint256 amount_guttys, uint256 amount_founts, address to, bytes calldata signature ) external payable { TokenData memory tokenData = _idToTokenData[id]; if ( tokenData.requiresSig && !_verifyMintSignature(id, amount_guttys, amount_founts, to, signature) ) { revert InvalidSignature(); } _collectEdition(id, amount_guttys, amount_founts, to, tokenData); } /** * @notice Internal function to mint some editions with some conditions * @dev Allows minting to a different address from msg.sender. * * Reverts if: * - the edition has not started * - the edition has ended * - msg.value does not equal the required amount * - the edition requires a Fount Card, but `to` does not hold one * * @param id The token id of the edition * @param amount_guttys The amount of editions to mint from the Gutty Kreum reserve * @param amount_founts The amount of editions to mint from the Fount Gallery Patron Card reserve * @param to The address to mint the token to * @param tokenData Information about the token */ function _collectEdition( uint256 id, uint256 amount_guttys, uint256 amount_founts, address to, TokenData memory tokenData ) internal { uint256 trueGuttysToMintAmount; uint256 trueFountsToMintAmount; // Check to see if the edition is mintable and the price is correct if (tokenData.startTime > block.timestamp) revert OpenEditionNotStartedYet(); if (tokenData.endTime > 0 && block.timestamp > tokenData.endTime) revert OpenEditionEnded(); if (msg.value > 0) revert IncorrectPaymentAmount(); // Check if it's a Fount Gallery exclusive if (tokenData.fountExclusive && !_isFountCardHolder(to)) revert RequiresFountCard(); // Check to see if the mint amounts exceed the reserves if ( GUTTY_KREUM_RESERVE <= tokenData.gutty_reserve_collected && FOUNT_PATRON_RESERVE <= tokenData.fount_reserve_collected ) revert SoldOut(); // If the amount of tokens to mint will exceed the Fount Patron Reserve, only mint the remaining amount // eg. 98/100 tokens minted, 5 tokens requested, only 2 tokens will be minted if (amount_founts > FOUNT_PATRON_RESERVE - tokenData.fount_reserve_collected) { trueFountsToMintAmount = FOUNT_PATRON_RESERVE - tokenData.fount_reserve_collected; } else { trueFountsToMintAmount = amount_founts; } // If the amount of tokens to mint will exceed the Gutty Kreum artwork holder Reserve, only mint the remaining amount // eg. 223/225 tokens minted, 5 tokens requested, only 2 tokens will be minted if (amount_guttys > GUTTY_KREUM_RESERVE - tokenData.gutty_reserve_collected) { trueGuttysToMintAmount = GUTTY_KREUM_RESERVE - tokenData.gutty_reserve_collected; } else { trueGuttysToMintAmount = amount_guttys; } // Add the new mint to the token data unchecked { tokenData.gutty_reserve_collected += trueGuttysToMintAmount; tokenData.fount_reserve_collected += trueFountsToMintAmount; } _idToTokenData[id] = tokenData; // Calculate the total amount of tokens to mint uint256 mintAmount = uint256(trueGuttysToMintAmount) + uint256(trueFountsToMintAmount); // Mint the NFT to the `to` address _mintToArtistFirst(to, id, mintAmount); emit CollectedOpenEdition(id); } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** ADD TOKEN DATA ----------------------------------------------------- */ /** * @notice Admin function to make a token available for sale * @dev As soon as the token data is registered, the NFT will be available to collect. * * Reverts if: * - `startTime` is zero (used to check if a token can be sold or not) * - `endTime` is in the past * - the token data already exists (to update token data, use the other admin * functions to set price and sale conditions) * * @param id The token id * @param price The sale price, if any * @param startTime The start time of the sale * @param endTime The end time of the sale, if any * @param mintPerAddress The max amount that can be minted for a wallet, if any * @param fountExclusive If the sale requires a Fount Gallery Patron card * @param requiresSig If the sale requires an off-chain signature */ function addTokenForSale( uint256 id, uint128 price, uint32 startTime, uint32 endTime, uint16 mintPerAddress, bool fountExclusive, bool requiresSig ) external onlyOwnerOrAdmin { // Check that start time is valid. This value is used to check if the token data // exists. Setting to zero will effectively "delete" the token data for other functions. if (startTime == 0) revert CannotSetStartTimeToZero(); // Check the end time is not in the past if (endTime > 0 && block.timestamp > endTime) revert CannotSetEndTimeToThePast(); TokenData memory tokenData = _idToTokenData[id]; // Check the token data is empty before adding if (tokenData.startTime != 0) revert TokenDataAlreadyExists(); // Set the new token data tokenData.price = price; tokenData.startTime = startTime; tokenData.endTime = endTime; tokenData.perAddressAllowance = mintPerAddress; tokenData.fountExclusive = fountExclusive; tokenData.requiresSig = requiresSig; _idToTokenData[id] = tokenData; emit TokenDataAdded(id, tokenData); } /** SET SALE PRICE ----------------------------------------------------- */ /** * @notice Admin function to update the sale price for a token * @dev Sets the start and end time values for a token. Setting `endTime` to zero * effectively keeps the edition open forever. * * Reverts if: * - `startTime` is zero (used to check if a token can be sold or not) * - `endTime` is in the past * - the token data does not exist, must be added with `addTokenForSale` first * * @param id The token id * @param startTime The new start time of the sale * @param endTime The new end time of the sale */ function setTokenSaleTimes( uint256 id, uint32 startTime, uint32 endTime ) external onlyOwnerOrAdmin { // Check that start time is not zero. This value is used to check if the token data // exists. Setting to zero will effectively "delete" the token data for other functions. if (startTime == 0) revert CannotSetStartTimeToZero(); // Check the end time is not in the past if (endTime > 0 && block.timestamp > endTime) revert CannotSetEndTimeToThePast(); TokenData memory tokenData = _idToTokenData[id]; // Check the token data already exists. // If not, it should be created with `addTokenForSale` first. if (tokenData.startTime == 0) revert TokenDataDoesNotExist(); // Set the new sale price tokenData.startTime = startTime; tokenData.endTime = endTime; _idToTokenData[id] = tokenData; emit TokenDataSaleTimesUpdated(id, tokenData); } /** SET SALE TIMES ----------------------------------------------------- */ /** * @notice Admin function to update the sale price for a token * @dev Reverts if the token data does not exist. Must be added with `addTokenForSale` first. * @param id The token id * @param price The new sale price */ function setTokenSalePrice(uint256 id, uint128 price) external onlyOwnerOrAdmin { TokenData memory tokenData = _idToTokenData[id]; // Check the token data already exists. // If not, it should be created with `addTokenForSale` first. if (tokenData.startTime == 0) revert TokenDataDoesNotExist(); // Set the new sale price tokenData.price = price; _idToTokenData[id] = tokenData; emit TokenDataSalePriceUpdated(id, tokenData); } /** SET SALE CONDITIONS ------------------------------------------------ */ /** * @notice Admin function to update the sale conditions for a token * @dev Reverts if the token data does not exist. Must be added with `addTokenForSale` first. * @param id The token id * @param mintPerAddress The max amount that can be minted for a wallet, if any * @param fountExclusive If the sale requires a Fount Gallery Patron card * @param requiresSig If the sale requires an off-chain signature */ function setTokenSaleConditions( uint256 id, uint16 mintPerAddress, bool fountExclusive, bool requiresSig ) external onlyOwnerOrAdmin { TokenData memory tokenData = _idToTokenData[id]; // Check the token data already exists. // If not, it should be created with `addTokenForSale` first. if (tokenData.startTime == 0) revert TokenDataDoesNotExist(); tokenData.perAddressAllowance = mintPerAddress; tokenData.fountExclusive = fountExclusive; tokenData.requiresSig = requiresSig; _idToTokenData[id] = tokenData; emit TokenDataSaleConditionsUpdated(id, tokenData); } /* ------------------------------------------------------------------------ G E T T E R S ------------------------------------------------------------------------ */ function tokenPrice(uint256 id) external view returns (uint256) { return _idToTokenData[id].price; } function tokenStartTime(uint256 id) external view returns (uint256) { return _idToTokenData[id].startTime; } function tokenEndTime(uint256 id) external view returns (uint256) { return _idToTokenData[id].endTime; } function tokenGuttyReserveCollectedCount(uint256 id) external view returns (uint256) { return _idToTokenData[id].gutty_reserve_collected; } function tokenFountReserveCollectedCount(uint256 id) external view returns (uint256) { return _idToTokenData[id].fount_reserve_collected; } function tokenAllowancePerAddress(uint256 id) external view returns (uint256) { return _idToTokenData[id].perAddressAllowance; } function tokenRemainingAllowanceForAddress( uint256 id, address account ) external view returns (uint256) { TokenData memory tokenData = _idToTokenData[id]; uint256 currentBalance = balanceOf[account][id]; uint256 remainingAllowance = currentBalance > tokenData.perAddressAllowance ? 0 : tokenData.perAddressAllowance - currentBalance; return remainingAllowance; } function tokenIsFountExclusive(uint256 id) external view returns (bool) { return _idToTokenData[id].fountExclusive; } function tokenRequiresOffChainSignatureToMint(uint256 id) external view returns (bool) { return _idToTokenData[id].requiresSig; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Optimized and flexible operator filterer to abide to OpenSea's /// mandatory on-chain royalty enforcement in order for new collections to /// receive royalties. /// For more information, see: /// See: https://github.com/ProjectOpenSea/operator-filter-registry abstract contract OperatorFilterer { /// @dev The default OpenSea operator blocklist subscription. address internal constant _DEFAULT_SUBSCRIPTION = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6; /// @dev The OpenSea operator filter registry. address internal constant _OPERATOR_FILTER_REGISTRY = 0x000000000000AAeB6D7670E522A718067333cd4E; /// @dev Registers the current contract to OpenSea's operator filter, /// and subscribe to the default OpenSea operator blocklist. /// Note: Will not revert nor update existing settings for repeated registration. function _registerForOperatorFiltering() internal virtual { _registerForOperatorFiltering(_DEFAULT_SUBSCRIPTION, true); } /// @dev Registers the current contract to OpenSea's operator filter. /// Note: Will not revert nor update existing settings for repeated registration. function _registerForOperatorFiltering(address subscriptionOrRegistrantToCopy, bool subscribe) internal virtual { /// @solidity memory-safe-assembly assembly { let functionSelector := 0x7d3e3dbe // `registerAndSubscribe(address,address)`. // Clean the upper 96 bits of `subscriptionOrRegistrantToCopy` in case they are dirty. subscriptionOrRegistrantToCopy := shr(96, shl(96, subscriptionOrRegistrantToCopy)) for {} iszero(subscribe) {} { if iszero(subscriptionOrRegistrantToCopy) { functionSelector := 0x4420e486 // `register(address)`. break } functionSelector := 0xa0af2903 // `registerAndCopyEntries(address,address)`. break } // Store the function selector. mstore(0x00, shl(224, functionSelector)) // Store the `address(this)`. mstore(0x04, address()) // Store the `subscriptionOrRegistrantToCopy`. mstore(0x24, subscriptionOrRegistrantToCopy) // Register into the registry. if iszero(call(gas(), _OPERATOR_FILTER_REGISTRY, 0, 0x00, 0x44, 0x00, 0x04)) { // If the function selector has not been overwritten, // it is an out-of-gas error. if eq(shr(224, mload(0x00)), functionSelector) { // To prevent gas under-estimation. revert(0, 0) } } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, because of Solidity's memory size limits. mstore(0x24, 0) } } /// @dev Modifier to guard a function and revert if the caller is a blocked operator. modifier onlyAllowedOperator(address from) virtual { if (from != msg.sender) { if (!_isPriorityOperator(msg.sender)) { if (_operatorFilteringEnabled()) _revertIfBlocked(msg.sender); } } _; } /// @dev Modifier to guard a function from approving a blocked operator.. modifier onlyAllowedOperatorApproval(address operator) virtual { if (!_isPriorityOperator(operator)) { if (_operatorFilteringEnabled()) _revertIfBlocked(operator); } _; } /// @dev Helper function that reverts if the `operator` is blocked by the registry. function _revertIfBlocked(address operator) private view { /// @solidity memory-safe-assembly assembly { // Store the function selector of `isOperatorAllowed(address,address)`, // shifted left by 6 bytes, which is enough for 8tb of memory. // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0xc6171134001122334455) // Store the `address(this)`. mstore(0x1a, address()) // Store the `operator`. mstore(0x3a, operator) // `isOperatorAllowed` always returns true if it does not revert. if iszero(staticcall(gas(), _OPERATOR_FILTER_REGISTRY, 0x16, 0x44, 0x00, 0x00)) { // Bubble up the revert if the staticcall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } // We'll skip checking if `from` is inside the blacklist. // Even though that can block transferring out of wrapper contracts, // we don't want tokens to be stuck. // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev For deriving contracts to override, so that operator filtering /// can be turned on / off. /// Returns true by default. function _operatorFilteringEnabled() internal view virtual returns (bool) { return true; } /// @dev For deriving contracts to override, so that preferred marketplaces can /// skip operator filtering, helping users save gas. /// Returns false for all inputs by default. function _isPriorityOperator(address) internal view virtual returns (bool) { return false; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.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 (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// 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 // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Simple owner and admin authentication * @notice Allows the management of a contract by using simple ownership and admin modifiers. */ abstract contract Auth { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @notice Current owner of the contract address public owner; /// @notice Current admins of the contract mapping(address => bool) public admins; /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ /** * @notice When the contract owner is updated * @param user The account that updated the new owner * @param newOwner The new owner of the contract */ event OwnerUpdated(address indexed user, address indexed newOwner); /** * @notice When an admin is added to the contract * @param user The account that added the new admin * @param newAdmin The admin that was added */ event AdminAdded(address indexed user, address indexed newAdmin); /** * @notice When an admin is removed from the contract * @param user The account that removed an admin * @param prevAdmin The admin that got removed */ event AdminRemoved(address indexed user, address indexed prevAdmin); /* ------------------------------------------------------------------------ M O D I F I E R S ------------------------------------------------------------------------ */ /** * @dev Only the owner can call */ modifier onlyOwner() { require(msg.sender == owner, "UNAUTHORIZED"); _; } /** * @dev Only an admin can call */ modifier onlyAdmin() { require(admins[msg.sender], "UNAUTHORIZED"); _; } /** * @dev Only the owner or an admin can call */ modifier onlyOwnerOrAdmin() { require((msg.sender == owner || admins[msg.sender]), "UNAUTHORIZED"); _; } /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @dev Sets the initial owner and a first admin upon creation. * @param owner_ The initial owner of the contract * @param admin_ An initial admin of the contract */ constructor(address owner_, address admin_) { owner = owner_; emit OwnerUpdated(address(0), owner_); admins[admin_] = true; emit AdminAdded(address(0), admin_); } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** * @notice Transfers ownership of the contract to `newOwner` * @dev Can only be called by the current owner or an admin * @param newOwner The new owner of the contract */ function setOwner(address newOwner) public virtual onlyOwnerOrAdmin { owner = newOwner; emit OwnerUpdated(msg.sender, newOwner); } /** * @notice Adds `newAdmin` as an amdin of the contract * @dev Can only be called by the current owner or an admin * @param newAdmin A new admin of the contract */ function addAdmin(address newAdmin) public virtual onlyOwnerOrAdmin { admins[newAdmin] = true; emit AdminAdded(address(0), newAdmin); } /** * @notice Removes `prevAdmin` as an amdin of the contract * @dev Can only be called by the current owner or an admin * @param prevAdmin The admin to remove */ function removeAdmin(address prevAdmin) public virtual onlyOwnerOrAdmin { admins[prevAdmin] = false; emit AdminRemoved(address(0), prevAdmin); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; import "openzeppelin/token/ERC1155/IERC1155.sol"; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Fount Gallery Card Check * @notice Utility functions to check ownership of a Fount Gallery Patron Card NFT */ contract FountCardCheck { /// @dev Address of the Fount Gallery Patron Card contract IERC1155 internal _fountCard; /// @dev Does not own a Fount Gallery Patron Card error NotFountCardHolder(); /** * @dev Does not own enough Fount Gallery Patron Cards * @param required The minimum amount of cards that need to be owned * @param owned The actualy amount of cards owned */ error DoesNotHoldEnoughFountCards(uint256 required, uint256 owned); /** * @dev Init with the Fount Gallery Patron Card contract address * @param fountCard The Fount Gallery Patron Card contract address */ constructor(address fountCard) { _fountCard = IERC1155(fountCard); } /** * @dev Modifier that only allows the caller to do something if they hold * a Fount Gallery Patron Card */ modifier onlyWhenFountCardHolder() { if (_getFountCardBalance(msg.sender) < 1) revert NotFountCardHolder(); _; } /** * @dev Modifier that only allows the caller to do something if they hold * at least a specific amount Fount Gallery Patron Cards * @param minAmount The minimum amount of cards that need to be owned */ modifier onlyWhenHoldingMinFountCards(uint256 minAmount) { uint256 balance = _getFountCardBalance(msg.sender); if (minAmount > balance) revert DoesNotHoldEnoughFountCards(minAmount, balance); _; } /** * @dev Get the number of Fount Gallery Patron Cards an address owns * @param owner The owner address to query * @return balance The balance of the owner */ function _getFountCardBalance(address owner) internal view returns (uint256 balance) { balance = _fountCard.balanceOf(owner, 1); } /** * @dev Check if an address holds at least one Fount Gallery Patron Card * @param owner The owner address to query * @return isHolder If the owner holds at least one card */ function _isFountCardHolder(address owner) internal view returns (bool isHolder) { isHolder = _getFountCardBalance(owner) > 0; } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Swappable metadata module * @notice Allows the use of a separate and swappable metadata contract */ abstract contract SwappableMetadata { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @notice Address of metadata contract address public metadata; /// @notice Flag for whether the metadata address can be updated or not bool public isMetadataLocked; /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ error MetadataLocked(); /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ /** * @dev When the metadata contract has been set * @param metadataContract The new metadata contract address */ event MetadataContractSet(address indexed metadataContract); /** * @dev When the metadata contract has been locked and is no longer swappable * @param metadataContract The final locked metadata contract address */ event MetadataContractLocked(address indexed metadataContract); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param metadata_ The address of the initial metadata contract */ constructor(address metadata_) { metadata = metadata_; emit MetadataContractSet(metadata_); } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** * @notice Sets the metadata address * @param metadata_ The new address of the metadata contract */ function _setMetadataAddress(address metadata_) internal { if (isMetadataLocked) revert MetadataLocked(); metadata = metadata_; emit MetadataContractSet(metadata_); } /** * @notice Sets the metadata address * @param metadata The new address of the metadata contract */ function setMetadataAddress(address metadata) public virtual; /** * @dev Locks the metadata address preventing further updates */ function _lockMetadata() internal { isMetadataLocked = true; emit MetadataContractLocked(metadata); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; import "openzeppelin/interfaces/IERC2981.sol"; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Royalty payments * @notice Support for the royalty standard (ERC-2981) */ abstract contract Royalties is IERC2981 { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @dev Store information about token royalties struct RoyaltyInfo { address receiver; uint96 amount; } /// @dev The current royalty information RoyaltyInfo internal _royaltyInfo; /// @dev Interface id for the royalty information standard /// bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a bytes4 internal constant ROYALTY_INTERFACE_ID = 0x2a55205a; /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ error MoreThanOneHundredPercentRoyalty(); /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ event RoyaltyInfoSet(address indexed receiver, uint256 indexed amount); event RoyaltyInfoUpdated(address indexed receiver, uint256 indexed amount); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param royaltiesReceiver The receiver of royalty payments * @param royaltiesAmount The royalty percentage with two decimals (10,000 = 100%) */ constructor(address royaltiesReceiver, uint256 royaltiesAmount) { _royaltyInfo = RoyaltyInfo(royaltiesReceiver, uint96(royaltiesAmount)); emit RoyaltyInfoSet(royaltiesReceiver, royaltiesAmount); } /* ------------------------------------------------------------------------ E R C 2 9 8 1 ------------------------------------------------------------------------ */ /// @notice EIP-2981 royalty standard for on-chain royalties function royaltyInfo(uint256, uint256 salePrice) public view virtual returns (address receiver, uint256 royaltyAmount) { receiver = _royaltyInfo.receiver; royaltyAmount = (salePrice * _royaltyInfo.amount) / 100_00; } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** * @dev Internal function to set the royalty information * @param receiver The receiver of royalty payments * @param amount The royalty percentage with two decimals (10,000 = 100%) */ function _setRoyaltyInfo(address receiver, uint256 amount) internal { if (amount > 100_00) revert MoreThanOneHundredPercentRoyalty(); _royaltyInfo = RoyaltyInfo(receiver, uint24(amount)); emit RoyaltyInfoUpdated(receiver, amount); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.15; import "openzeppelin/token/ERC20/IERC20.sol"; import "openzeppelin/token/ERC721/IERC721.sol"; import "openzeppelin/token/ERC1155/IERC1155.sol"; /** * @author Sam King (samkingstudio.eth) for Fount Gallery * @title Withdraw ETH and tokens module * @notice Allows the withdrawal of ETH, ERC20, ERC721, an ERC1155 tokens */ abstract contract Withdraw { /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ error CannotWithdrawToZeroAddress(); error WithdrawFailed(); error BalanceTooLow(); error ZeroBalance(); /* ------------------------------------------------------------------------ W I T H D R A W ------------------------------------------------------------------------ */ function _withdrawETH(address to) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check there is eth to withdraw uint256 balance = address(this).balance; if (balance == 0) revert ZeroBalance(); // Transfer funds (bool success, ) = payable(to).call{value: balance}(""); if (!success) revert WithdrawFailed(); } function _withdrawToken(address tokenAddress, address to) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check there are tokens to withdraw uint256 balance = IERC20(tokenAddress).balanceOf(address(this)); if (balance == 0) revert ZeroBalance(); // Transfer tokens bool success = IERC20(tokenAddress).transfer(to, balance); if (!success) revert WithdrawFailed(); } function _withdrawERC721Token( address tokenAddress, uint256 id, address to ) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check the NFT is in this contract address owner = IERC721(tokenAddress).ownerOf(id); if (owner != address(this)) revert ZeroBalance(); // Transfer NFT IERC721(tokenAddress).transferFrom(address(this), to, id); } function _withdrawERC1155Token( address tokenAddress, uint256 id, uint256 amount, address to ) internal { // Prevent withdrawing to the zero address if (to == address(0)) revert CannotWithdrawToZeroAddress(); // Check the tokens are owned by this contract, and there's at least `amount` uint256 balance = IERC1155(tokenAddress).balanceOf(address(this), id); if (balance == 0) revert ZeroBalance(); if (amount > balance) revert BalanceTooLow(); // Transfer tokens IERC1155(tokenAddress).safeTransferFrom(address(this), to, id, amount, ""); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; import "solmate/tokens/ERC1155.sol"; import "fount-contracts/auth/Auth.sol"; import "fount-contracts/community/FountCardCheck.sol"; import "fount-contracts/extensions/SwappableMetadata.sol"; import "fount-contracts/utils/Royalties.sol"; import "fount-contracts/utils/Withdraw.sol"; import "closedsea/OperatorFilterer.sol"; import "openzeppelin/utils/cryptography/ECDSA.sol"; import "openzeppelin/utils/cryptography/EIP712.sol"; import "openzeppelin/token/ERC20/IERC20.sol"; import "./interfaces/IMetadata.sol"; import "./interfaces/IMorningsPayments.sol"; import "./interfaces/IWETH.sol"; /** * @author Fount Gallery * @title ERC1155Base * @notice Base contract for Mornings Open Editions to inherit from * * Features: * - EIP-712 signature minting and verification * - On-chain checking of Fount Gallery Patron cards for minting * - Swappable metadata contract * - On-chain royalties standard (EIP-2981) * - Support for OpenSea's Operator Filterer to allow royalties */ abstract contract ERC1155Base is ERC1155, Auth, FountCardCheck, SwappableMetadata, Royalties, Withdraw, EIP712, OperatorFilterer { /* ------------------------------------------------------------------------ S T O R A G E ------------------------------------------------------------------------ */ /// @notice Gutty Kreum address public artist = 0x95D89b7069D3e401EfE987a94e4cC4C64Af746Fb; /// @notice Contract information string public contractURI; /// @notice Contract name string public name = "Mornings"; /// @notice Contract symbol string public symbol = "GKAM"; /// @notice EIP-712 signing domain string public constant SIGNING_DOMAIN = "MorningsOpenEditions"; /// @notice EIP-712 signature version string public constant SIGNATURE_VERSION = "1"; /// @notice EIP-712 signed data type hash for minting with an off-chain signature bytes32 public constant MINT_SIGNATURE_TYPEHASH = keccak256( "MintSignatureData(uint256 id,uint256 amount_guttys,uint256 amount_founts,address to,uint256 nonce)" ); /// @dev EIP-712 signed data struct for minting with an off-chain signature struct MintSignatureData { uint256 id; uint256 amount_guttys; uint256 amount_founts; address to; uint256 nonce; bytes signature; } /// @notice Approved signer public addresses mapping(address => bool) public approvedSigners; /// @notice Nonce management to avoid signature replay attacks mapping(address => uint256) public nonces; /// @notice If operator filtering is applied bool public operatorFilteringEnabled; /// @notice Wrapped ETH contract address for safe ETH transfer fallbacks address public weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; /// @notice Address where proceeds should be sent address public payments; /* ------------------------------------------------------------------------ E R R O R S ------------------------------------------------------------------------ */ error CannotSetPaymentAddressToZero(); /* ------------------------------------------------------------------------ E V E N T S ------------------------------------------------------------------------ */ event Init(); /* ------------------------------------------------------------------------ I N I T ------------------------------------------------------------------------ */ /** * @param owner_ The owner of the contract * @param admin_ The admin of the contract * @param payments_ The admin of the contract * @param royaltiesAmount_ The royalty percentage with two decimals (10,000 = 100%) * @param metadata_ The initial metadata contract address * @param fountCard_ The address of the Fount Gallery Patron Card */ constructor( address owner_, address admin_, address payments_, uint256 royaltiesAmount_, address metadata_, address fountCard_ ) ERC1155() Auth(owner_, admin_) FountCardCheck(fountCard_) SwappableMetadata(metadata_) Royalties(payments_, royaltiesAmount_) EIP712(SIGNING_DOMAIN, SIGNATURE_VERSION) { payments = payments_; _registerForOperatorFiltering(); operatorFilteringEnabled = true; emit Init(); } /* ------------------------------------------------------------------------ A R T I S T M I N T I N G ------------------------------------------------------------------------ */ function _mintToArtistFirst(address to, uint256 id, uint256 amount) internal { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), artist, id, amount); emit TransferSingle(msg.sender, artist, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, artist, id, amount, "") == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } /* ------------------------------------------------------------------------ S I G N A T U R E V E R I F I C A T I O N ------------------------------------------------------------------------ */ /** * @notice Internal function to verify an EIP-712 minting signature * @param id The token id * @param to The account that has approval to mint * @param signature The EIP-712 signature * @return bool If the signature is verified or not */ function _verifyMintSignature( uint256 id, uint256 amount_guttys, uint256 amount_founts, address to, bytes calldata signature ) internal returns (bool) { MintSignatureData memory data = MintSignatureData({ id: id, amount_guttys: amount_guttys, amount_founts: amount_founts, to: to, nonce: nonces[to], signature: signature }); // Hash the data for verification bytes32 digest = _hashTypedDataV4( keccak256( abi.encode( MINT_SIGNATURE_TYPEHASH, data.id, data.amount_guttys, data.amount_founts, data.to, nonces[data.to]++ ) ) ); // Verifiy signature is ok address addr = ECDSA.recover(digest, data.signature); return approvedSigners[addr] && addr != address(0); } /* ------------------------------------------------------------------------ A D M I N ------------------------------------------------------------------------ */ /** SIGNERS ------------------------------------------------------------ */ /** * @notice Admin function to set an EIP-712 signer address * @param signer The address of the new signer * @param approved If the signer is approved */ function setSigner(address signer, bool approved) external onlyOwnerOrAdmin { approvedSigners[signer] = approved; } /** METADATA ----------------------------------------------------------- */ /** * @notice Admin function to set the metadata contract address * @param metadata The new metadata contract address */ function setMetadataAddress(address metadata) public override onlyOwnerOrAdmin { _setMetadataAddress(metadata); } /** * @notice Admin function to set the contract URI for marketplaces * @param contractURI_ The new contract URI */ function setContractURI(string memory contractURI_) external onlyOwnerOrAdmin { contractURI = contractURI_; } /** ROYALTIES ---------------------------------------------------------- */ /** * @notice Admin function to set the royalty information * @param receiver The receiver of royalty payments * @param amount The royalty percentage with two decimals (10,000 = 100%) */ function setRoyaltyInfo(address receiver, uint256 amount) external onlyOwnerOrAdmin { _setRoyaltyInfo(receiver, amount); } /** * @notice Admin function to set whether OpenSea's Operator Filtering should be enabled * @param enabled If the operator filtering should be enabled */ function setOperatorFilteringEnabled(bool enabled) external onlyOwnerOrAdmin { operatorFilteringEnabled = enabled; } function registerForOperatorFiltering( address subscriptionOrRegistrantToCopy, bool subscribe ) external onlyOwnerOrAdmin { _registerForOperatorFiltering(subscriptionOrRegistrantToCopy, subscribe); } /** PAYMENTS ----------------------------------------------------------- */ /** * @notice Admin function to set the payment address for withdrawing funds * @param paymentAddress The new address where payments should be sent upon withdrawal */ function setPaymentAddress(address paymentAddress) external onlyOwnerOrAdmin { if (paymentAddress == address(0)) revert CannotSetPaymentAddressToZero(); payments = paymentAddress; } /* ------------------------------------------------------------------------ R O T A L T I E S ------------------------------------------------------------------------ */ /** * @notice Add interface for on-chain royalty standard */ function supportsInterface( bytes4 interfaceId ) public view override(ERC1155, IERC165) returns (bool) { return interfaceId == ROYALTY_INTERFACE_ID || super.supportsInterface(interfaceId); } /** * @notice Repeats the OpenSea Operator Filtering registration */ function repeatRegistration() public { _registerForOperatorFiltering(); } /** * @notice Override ERC-1155 `setApprovalForAll` to support OpenSea Operator Filtering */ function setApprovalForAll( address operator, bool approved ) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } /** * @notice Override ERC-1155 `safeTransferFrom` to support OpenSea Operator Filtering */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, id, amount, data); } /** * @notice Override ERC-1155 `safeTransferFrom` to support OpenSea Operator Filtering */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual override onlyAllowedOperator(from) { super.safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Overrde `OperatorFilterer._operatorFilteringEnabled` to return whether * the operator filtering is enabled in this contract. */ function _operatorFilteringEnabled() internal view virtual override returns (bool) { return operatorFilteringEnabled; } /* ------------------------------------------------------------------------ S A F E T R A N S F E R S ------------------------------------------------------------------------ */ /** * @notice Safely transfer ETH by wrapping as WETH if the ETH transfer fails * @param to The address to transfer ETH/WETH to * @param amount The amount of ETH/WETH to transfer */ function _transferETHWithFallback(address to, uint256 amount) internal { if (!_transferETH(to, amount)) { IWETH(weth).deposit{value: amount}(); IERC20(weth).transfer(to, amount); } } /** * @notice Transfer ETH and return the success status. * @param to The address to transfer ETH to * @param amount The amount of ETH to transfer */ function _transferETH(address to, uint256 amount) internal returns (bool) { (bool success, ) = payable(to).call{value: amount}(new bytes(0)); return success; } /* ------------------------------------------------------------------------ E R C 1 1 5 5 ------------------------------------------------------------------------ */ /** * @notice Returns the token metadata * @return id The token id to get metadata for */ function uri(uint256 id) public view override returns (string memory) { return IMetadata(metadata).tokenURI(id); } /** * @notice Burn a token. You can only burn tokens you own. * @param id The token id to burn * @param amount The amount to burn */ function burn(uint256 id, uint256 amount) external { require(balanceOf[msg.sender][id] >= amount, "CANNOT_BURN"); _burn(msg.sender, id, amount); } /* ------------------------------------------------------------------------ W I T H D R A W ------------------------------------------------------------------------ */ /** * @notice Admin function to withdraw ETH from this contract * @dev Withdraws to the `payments` address. * * Reverts if: * - there are active auctions * - the payments address is set to zero * */ function withdrawETH() public onlyOwnerOrAdmin { // Send the eth to the payments address _withdrawETH(payments); } /** * @notice Admin function to withdraw ETH from this contract and release from payments contract * @dev Withdraws to the `payments` address, then calls `releaseAllETH` as a splitter. * * Reverts if: * - there are active auctions * - the payments address is set to zero * */ function withdrawAndReleaseAllETH() public onlyOwnerOrAdmin { // Send the eth to the payments address _withdrawETH(payments); // And then release all the ETH to the payees IMorningsPayments(payments).releaseAllETH(); } /** * @notice Admin function to withdraw ERC-20 tokens from this contract * @dev Withdraws to the `payments` address. * * Reverts if: * - the payments address is set to zero * */ function withdrawTokens(address tokenAddress) public onlyOwnerOrAdmin { // Send the tokens to the payments address _withdrawToken(tokenAddress, payments); } /** * @notice Admin function to withdraw ERC-20 tokens from this contract * @param to The address to send the ERC-20 tokens to */ function withdrawTokens(address tokenAddress, address to) public onlyOwnerOrAdmin { _withdrawToken(tokenAddress, to); } }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; interface IMetadata { function tokenURI(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; interface IMorningsPayments { function releaseAllETH() external; function releaseAllToken(address tokenAddress) external; }
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.17; interface IWETH { function deposit() external payable; function withdraw(uint256 wad) external; function transfer(address to, uint256 value) external returns (bool); }
{ "remappings": [ "closedsea/=packages/contracts/lib/closedsea/src/", "ds-test/=packages/contracts/lib/ds-test/src/", "erc4626-tests/=packages/contracts/lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a-upgradeable/=packages/contracts/lib/closedsea/lib/erc721a-upgradeable/contracts/", "erc721a/=packages/contracts/lib/closedsea/lib/erc721a/contracts/", "ethier/=packages/contracts/lib/ethier/", "forge-std/=packages/contracts/lib/forge-std/src/", "fount-contracts/=packages/contracts/lib/fount-contracts/src/", "openzeppelin-contracts-upgradeable/=packages/contracts/lib/closedsea/lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=packages/contracts/lib/openzeppelin-contracts/", "openzeppelin/=packages/contracts/lib/fount-contracts/lib/openzeppelin-contracts/contracts/", "operator-filter-registry/=packages/contracts/lib/closedsea/lib/operator-filter-registry/", "solmate/=packages/contracts/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"admin_","type":"address"},{"internalType":"address","name":"payments_","type":"address"},{"internalType":"uint256","name":"royaltiesAmount_","type":"uint256"},{"internalType":"address","name":"metadata_","type":"address"},{"internalType":"address","name":"fountCard_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AmountExceedsMaxWalletMint","type":"error"},{"inputs":[],"name":"AmountExceedsWalletAllowance","type":"error"},{"inputs":[],"name":"BalanceTooLow","type":"error"},{"inputs":[],"name":"BatchAlreadyMinted","type":"error"},{"inputs":[],"name":"CannotSetEndTimeToThePast","type":"error"},{"inputs":[],"name":"CannotSetPaymentAddressToZero","type":"error"},{"inputs":[],"name":"CannotSetStartTimeToZero","type":"error"},{"inputs":[],"name":"CannotWithdrawToZeroAddress","type":"error"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"owned","type":"uint256"}],"name":"DoesNotHoldEnoughFountCards","type":"error"},{"inputs":[],"name":"IncorrectPaymentAmount","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"MetadataLocked","type":"error"},{"inputs":[],"name":"MoreThanOneHundredPercentRoyalty","type":"error"},{"inputs":[],"name":"NotForSale","type":"error"},{"inputs":[],"name":"NotFountCardHolder","type":"error"},{"inputs":[],"name":"OpenEditionEnded","type":"error"},{"inputs":[],"name":"OpenEditionNotStartedYet","type":"error"},{"inputs":[],"name":"RequiresFountCard","type":"error"},{"inputs":[],"name":"RequiresSignature","type":"error"},{"inputs":[],"name":"SoldOut","type":"error"},{"inputs":[],"name":"TokenDataAlreadyExists","type":"error"},{"inputs":[],"name":"TokenDataDoesNotExist","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"inputs":[],"name":"ZeroBalance","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"prevAdmin","type":"address"}],"name":"AdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"CollectedOpenEdition","type":"event"},{"anonymous":false,"inputs":[],"name":"Init","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"metadataContract","type":"address"}],"name":"MetadataContractLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"metadataContract","type":"address"}],"name":"MetadataContractSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RoyaltyInfoSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RoyaltyInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint256","name":"gutty_reserve_collected","type":"uint256"},{"internalType":"uint256","name":"fount_reserve_collected","type":"uint256"},{"internalType":"uint16","name":"perAddressAllowance","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"}],"indexed":false,"internalType":"struct MorningsOpenEditions.TokenData","name":"tokenData","type":"tuple"}],"name":"TokenDataAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint256","name":"gutty_reserve_collected","type":"uint256"},{"internalType":"uint256","name":"fount_reserve_collected","type":"uint256"},{"internalType":"uint16","name":"perAddressAllowance","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"}],"indexed":false,"internalType":"struct MorningsOpenEditions.TokenData","name":"tokenData","type":"tuple"}],"name":"TokenDataSaleConditionsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint256","name":"gutty_reserve_collected","type":"uint256"},{"internalType":"uint256","name":"fount_reserve_collected","type":"uint256"},{"internalType":"uint16","name":"perAddressAllowance","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"}],"indexed":false,"internalType":"struct MorningsOpenEditions.TokenData","name":"tokenData","type":"tuple"}],"name":"TokenDataSalePriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint256","name":"gutty_reserve_collected","type":"uint256"},{"internalType":"uint256","name":"fount_reserve_collected","type":"uint256"},{"internalType":"uint16","name":"perAddressAllowance","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"}],"indexed":false,"internalType":"struct MorningsOpenEditions.TokenData","name":"tokenData","type":"tuple"}],"name":"TokenDataSaleTimesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"FOUNT_PATRON_RESERVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUTTY_KREUM_RESERVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_SIGNATURE_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNATURE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNING_DOMAIN","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_artistBatchMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint128","name":"price","type":"uint128"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint16","name":"mintPerAddress","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"}],"name":"addTokenForSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"admins","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedSigners","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"artist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"balances","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount_guttys","type":"uint256"},{"internalType":"uint256","name":"amount_founts","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"collectEdition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount_guttys","type":"uint256"},{"internalType":"uint256","name":"amount_founts","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"collectEdition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMetadataLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadata","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintArtistBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"operatorFilteringEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"payments","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"subscriptionOrRegistrantToCopy","type":"address"},{"internalType":"bool","name":"subscribe","type":"bool"}],"name":"registerForOperatorFiltering","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"prevAdmin","type":"address"}],"name":"removeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"repeatRegistration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"contractURI_","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"metadata","type":"address"}],"name":"setMetadataAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setOperatorFilteringEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"paymentAddress","type":"address"}],"name":"setPaymentAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setRoyaltyInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint16","name":"mintPerAddress","type":"uint16"},{"internalType":"bool","name":"fountExclusive","type":"bool"},{"internalType":"bool","name":"requiresSig","type":"bool"}],"name":"setTokenSaleConditions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint128","name":"price","type":"uint128"}],"name":"setTokenSalePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"setTokenSaleTimes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenAllowancePerAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenEndTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenFountReserveCollectedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenGuttyReserveCollectedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenIsFountExclusive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"tokenRemainingAllowanceForAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenRequiresOffChainSignatureToMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAndReleaseAllETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
600780546001600160a01b0319167395d89b7069d3e401efe987a94e4cc4c64af746fb1790556101806040526008610140908152674d6f726e696e677360c01b61016052600990620000529082620004eb565b50604080518082019091526004815263474b414d60e01b6020820152600a906200007d9082620004eb565b50600d8054610100600160a81b03191674c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2001790556010805460ff19169055348015620000bd57600080fd5b5060405162004bdb38038062004bdb833981016040819052620000e091620005d4565b8585858585856040518060400160405280601481526020017f4d6f726e696e67734f70656e45646974696f6e73000000000000000000000000815250604051806040016040528060018152602001603160f81b815250858585858b8b81600260006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b031660006001600160a01b03167f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7660405160405180910390a36001600160a01b038116600081815260036020526040808220805460ff19166001179055517fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b908290a35050600480546001600160a01b039283166001600160a01b0319918216179091556005805492841692909116821790556040517f0713c9f4b0c5db294e61505e6819f6ad0cccf782df1a544939dc55d13fe7fc1c90600090a2506040805180820182526001600160a01b0384168082526001600160601b0384166020909201829052600160a01b909102811760065590518291907f984cbbb47b413608120ad6b444ea0004fe19b6f88a5c0992e612b97fd3cb631e90600090a35050815160208084019190912082518383012060e08290526101008190524660a0818152604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81880181905281830187905260608201869052608082019490945230818401528151808203909301835260c00190528051940193909320919290916080523060c052610120525050600e80546001600160a01b0319166001600160a01b03881617905550620003619050620003a9565b600d805460ff191660011790556040517f57a86f7d14ccde89e22870afe839e3011216827daa9b24e18629f0a1e9d6cc1490600090a15050505050505050505050506200064c565b620003ca733cc6cdda760b79bafa08df41ecfa224f810dceb66001620003cc565b565b6001600160a01b0390911690637d3e3dbe81620003fc5782620003f55750634420e486620003fc565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af16200043c578060005160e01c036200043c57600080fd5b5060006024525050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200047157607f821691505b6020821081036200049257634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620004e657600081815260208120601f850160051c81016020861015620004c15750805b601f850160051c820191505b81811015620004e257828155600101620004cd565b5050505b505050565b81516001600160401b0381111562000507576200050762000446565b6200051f816200051884546200045c565b8462000498565b602080601f8311600181146200055757600084156200053e5750858301515b600019600386901b1c1916600185901b178555620004e2565b600085815260208120601f198616915b82811015620005885788860151825594840194600190910190840162000567565b5085821015620005a75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80516001600160a01b0381168114620005cf57600080fd5b919050565b60008060008060008060c08789031215620005ee57600080fd5b620005f987620005b7565b95506200060960208801620005b7565b94506200061960408801620005b7565b9350606087015192506200063060808801620005b7565b91506200064060a08801620005b7565b90509295509295509295565b60805160a05160c05160e051610100516101205161453f6200069c600039600061361701526000613666015260006136410152600061359a015260006135c4015260006135ee015261453f6000f3fe6080604052600436106103955760003560e01c8063881ced95116101dc578063c0fd735b11610102578063e2e784d5116100a0578063ecd8dbf71161006f578063ecd8dbf714610bc8578063f242432a14610be8578063fb796e6c14610c08578063fd6724fc14610c2257600080fd5b8063e2e784d514610b18578063e3faad9414610b38578063e8a3d48514610b78578063e985e9c514610b8d57600080fd5b8063de7ff469116100dc578063de7ff46914610aa9578063df27092014610ac9578063e086e5ec14610ae3578063e17b25af14610af857600080fd5b8063c0fd735b14610a3d578063d4ddce8a14610a52578063d7e45cd714610a8857600080fd5b8063a41572961161017a578063b05fc5cc11610149578063b05fc5cc146109d5578063b390c0ab146109e8578063b7c0b8e814610a08578063c01c3c9c14610a2857600080fd5b8063a415729614610934578063a522ad2514610961578063a6d23e1014610981578063af4fddfa146109a157600080fd5b80638da5cb5b116101b65780638da5cb5b146108bf578063938e3d7b146108df57806395d89b41146108ff578063a22cb4651461091457600080fd5b8063881ced951461083557806389d020dc1461086f5780638a8755121461088f57600080fd5b806343bc1612116102c157806358a478ed1161025f578063704802751161022e57806370480275146107b35780637c1a8343146107d35780637ecebe00146107f35780637f20256a1461082057600080fd5b806358a478ed146107145780635e1c0746146107445780635e1e1004146107595780636b2a9d251461077957600080fd5b806349df728c1161029b57806349df728c146106825780634d820b4f146106a25780634e1273f4146106d2578063582e8ae5146106ff57600080fd5b806343bc16121461060e578063453722411461062e57806346d8efad1461066257600080fd5b80631785f53c1161033957806331cb61051161030857806331cb610514610561578063392f37e9146105815780633fc8cef3146105b9578063429b62e5146105de57600080fd5b80631785f53c146104a957806326645a2c146104c95780632a55205a146105025780632eb2c2d61461054157600080fd5b80630651efa3116103755780630651efa31461043457806306fdde03146104475780630e89341c1461046957806313af40351461048957600080fd5b8062029eb81461039a578062fdd58e146103bc57806301ffc9a714610404575b600080fd5b3480156103a657600080fd5b506103ba6103b5366004613957565b610c5c565b005b3480156103c857600080fd5b506103f16103d73660046139f3565b600060208181529281526040808220909352908152205481565b6040519081526020015b60405180910390f35b34801561041057600080fd5b5061042461041f366004613a33565b610f84565b60405190151581526020016103fb565b6103ba610442366004613a57565b610faf565b34801561045357600080fd5b5061045c611075565b6040516103fb9190613aba565b34801561047557600080fd5b5061045c610484366004613aed565b611103565b34801561049557600080fd5b506103ba6104a4366004613b06565b611175565b3480156104b557600080fd5b506103ba6104c4366004613b06565b611205565b3480156104d557600080fd5b506104246104e4366004613aed565b6000908152600f602052604090206003015462010000900460ff1690565b34801561050e57600080fd5b5061052261051d366004613b21565b611293565b604080516001600160a01b0390931683526020830191909152016103fb565b34801561054d57600080fd5b506103ba61055c366004613bca565b6112da565b34801561056d57600080fd5b506103ba61057c366004613c85565b61131a565b34801561058d57600080fd5b506005546105a1906001600160a01b031681565b6040516001600160a01b0390911681526020016103fb565b3480156105c557600080fd5b50600d546105a19061010090046001600160a01b031681565b3480156105ea57600080fd5b506104246105f9366004613b06565b60036020526000908152604090205460ff1681565b34801561061a57600080fd5b506007546105a1906001600160a01b031681565b34801561063a57600080fd5b506103f1610649366004613aed565b6000908152600f602052604090206003015461ffff1690565b34801561066e57600080fd5b506103ba61067d366004613c85565b611389565b34801561068e57600080fd5b506103ba61069d366004613b06565b6113db565b3480156106ae57600080fd5b506103f16106bd366004613aed565b6000908152600f602052604090206002015490565b3480156106de57600080fd5b506106f26106ed366004613cbc565b611439565b6040516103fb9190613d28565b34801561070b57600080fd5b506103f160e181565b34801561072057600080fd5b506103f161072f366004613aed565b6000908152600f602052604090206001015490565b34801561075057600080fd5b506103ba61156e565b34801561076557600080fd5b506103ba610774366004613b06565b611578565b34801561078557600080fd5b50610424610794366004613aed565b6000908152600f60205260409020600301546301000000900460ff1690565b3480156107bf57600080fd5b506103ba6107ce366004613b06565b611605565b3480156107df57600080fd5b506103ba6107ee366004613d6c565b611696565b3480156107ff57600080fd5b506103f161080e366004613b06565b600c6020526000908152604090205481565b34801561082c57600080fd5b506103f1606481565b34801561084157600080fd5b506103f1610850366004613aed565b6000908152600f6020526040902054600160801b900463ffffffff1690565b34801561087b57600080fd5b506103ba61088a366004613d8f565b61188e565b34801561089b57600080fd5b506104246108aa366004613b06565b600b6020526000908152604090205460ff1681565b3480156108cb57600080fd5b506002546105a1906001600160a01b031681565b3480156108eb57600080fd5b506103ba6108fa366004613e4f565b611a97565b34801561090b57600080fd5b5061045c611ae7565b34801561092057600080fd5b506103ba61092f366004613c85565b611af4565b34801561094057600080fd5b5061045c604051806040016040528060018152602001603160f81b81525081565b34801561096d57600080fd5b506103ba61097c366004613ecf565b611b18565b34801561098d57600080fd5b50600e546105a1906001600160a01b031681565b3480156109ad57600080fd5b506103f17f3ebe2a8026435bce72f492f4f1687396bda15f10d2b8fe0db69d6dbaf7564a2b81565b6103ba6109e3366004613ef9565b611b66565b3480156109f457600080fd5b506103ba610a03366004613b21565b611c47565b348015610a1457600080fd5b506103ba610a23366004613f6a565b611ca8565b348015610a3457600080fd5b506103ba611cff565b348015610a4957600080fd5b506103ba61202f565b348015610a5e57600080fd5b506103f1610a6d366004613aed565b6000908152600f60205260409020546001600160801b031690565b348015610a9457600080fd5b5060055461042490600160a01b900460ff1681565b348015610ab557600080fd5b506103f1610ac4366004613f87565b6120f2565b348015610ad557600080fd5b506010546104249060ff1681565b348015610aef57600080fd5b506103ba6121d2565b348015610b0457600080fd5b506103ba610b13366004613b06565b61222b565b348015610b2457600080fd5b506103ba610b333660046139f3565b612278565b348015610b4457600080fd5b5061045c604051806040016040528060148152602001734d6f726e696e67734f70656e45646974696f6e7360601b81525081565b348015610b8457600080fd5b5061045c6122c6565b348015610b9957600080fd5b50610424610ba8366004613ecf565b600160209081526000928352604080842090915290825290205460ff1681565b348015610bd457600080fd5b506103ba610be3366004613faa565b6122d3565b348015610bf457600080fd5b506103ba610c03366004613fe6565b61252f565b348015610c1457600080fd5b50600d546104249060ff1681565b348015610c2e57600080fd5b506103f1610c3d366004613aed565b6000908152600f6020526040902054600160a01b900463ffffffff1690565b6002546001600160a01b0316331480610c8457503360009081526003602052604090205460ff165b610ca95760405162461bcd60e51b8152600401610ca090614040565b60405180910390fd5b8463ffffffff16600003610cd0576040516361bc7fb160e11b815260040160405180910390fd5b60008463ffffffff16118015610ceb57508363ffffffff1642115b15610d095760405163312728dd60e11b815260040160405180910390fd5b6000878152600f602090815260409182902082516101008101845281546001600160801b038116825263ffffffff600160801b82048116948301859052600160a01b909104169381019390935260018101546060840152600281015460808401526003015461ffff811660a084015260ff6201000082048116151560c0850152630100000090910416151560e083015215610db7576040516320705a1b60e11b815260040160405180910390fd5b8681600001906001600160801b031690816001600160801b03168152505085816020019063ffffffff16908163ffffffff168152505084816040019063ffffffff16908163ffffffff1681525050838160a0019061ffff16908161ffff1681525050828160c0019015159081151581525050818160e001901515908115158152505080600f60008a815260200190815260200160002060008201518160000160006101000a8154816001600160801b0302191690836001600160801b0316021790555060208201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160146101000a81548163ffffffff021916908363ffffffff160217905550606082015181600101556080820151816002015560a08201518160030160006101000a81548161ffff021916908361ffff16021790555060c08201518160030160026101000a81548160ff02191690831515021790555060e08201518160030160036101000a81548160ff021916908315150217905550905050877f14eb4bf6c7d72fc73e72c7352fc7607a0ac11969cadce90af77c0540a7b0c33082604051610f729190614066565b60405180910390a25050505050505050565b60006001600160e01b0319821663152a902d60e11b1480610fa95750610fa982612562565b92915050565b6000848152600f602090815260409182902082516101008101845281546001600160801b038116825263ffffffff600160801b8204811694830194909452600160a01b900490921692820192909252600182015460608201526002820154608082015260039091015461ffff811660a083015260ff6201000082048116151560c084015263010000009091041615801560e083015261106157604051630426ff7760e01b815260040160405180910390fd5b61106e85858585856125b0565b5050505050565b60098054611082906140ec565b80601f01602080910402602001604051908101604052809291908181526020018280546110ae906140ec565b80156110fb5780601f106110d0576101008083540402835291602001916110fb565b820191906000526020600020905b8154815290600101906020018083116110de57829003601f168201915b505050505081565b60055460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd90602401600060405180830381865afa15801561114d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fa99190810190614126565b6002546001600160a01b031633148061119d57503360009081526003602052604090205460ff165b6111b95760405162461bcd60e51b8152600401610ca090614040565b600280546001600160a01b0319166001600160a01b03831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b6002546001600160a01b031633148061122d57503360009081526003602052604090205460ff165b6112495760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b038116600081815260036020526040808220805460ff19169055517fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce908290a350565b6006546001600160a01b03811690600090612710906112c790600160a01b90046bffffffffffffffffffffffff16856141b3565b6112d191906141ca565b90509250929050565b876001600160a01b03811633146112ff57600d5460ff16156112ff576112ff33612829565b61130f898989898989898961286d565b505050505050505050565b6002546001600160a01b031633148061134257503360009081526003602052604090205460ff165b61135e5760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b03919091166000908152600b60205260409020805460ff1916911515919091179055565b6002546001600160a01b03163314806113b157503360009081526003602052604090205460ff165b6113cd5760405162461bcd60e51b8152600401610ca090614040565b6113d78282612b10565b5050565b6002546001600160a01b031633148061140357503360009081526003602052604090205460ff165b61141f5760405162461bcd60e51b8152600401610ca090614040565b600e546114369082906001600160a01b0316612b85565b50565b606083821461147c5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b6044820152606401610ca0565b8367ffffffffffffffff81111561149557611495613de0565b6040519080825280602002602001820160405280156114be578160200160208202803683370190505b50905060005b84811015611565576000808787848181106114e1576114e16141ec565b90506020020160208101906114f69190613b06565b6001600160a01b03166001600160a01b03168152602001908152602001600020600085858481811061152a5761152a6141ec565b90506020020135815260200190815260200160002054828281518110611552576115526141ec565b60209081029190910101526001016114c4565b50949350505050565b611576612cd1565b565b6002546001600160a01b03163314806115a057503360009081526003602052604090205460ff165b6115bc5760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b0381166115e357604051631f4c499760e01b815260040160405180910390fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031633148061162d57503360009081526003602052604090205460ff165b6116495760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b038116600081815260036020526040808220805460ff19166001179055517fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b908290a350565b6002546001600160a01b03163314806116be57503360009081526003602052604090205460ff165b6116da5760405162461bcd60e51b8152600401610ca090614040565b6000828152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b82048116958301869052600160a01b909104169281019290925260018101546060830152600281015460808301526003015461ffff811660a083015260ff6201000082048116151560c0840152630100000090910416151560e08201529103611788576040516347c0cce560e01b815260040160405180910390fd5b6001600160801b0380831682526000848152600f602090815260409182902084518154928601518487015163ffffffff908116600160a01b0263ffffffff60a01b1991909216600160801b026001600160a01b031990951692909616919091179290921793909316178255606083015160018301556080830151600283015560a08301516003909201805460c085015160e0860151151563010000000263ff00000019911515620100000262ffffff1990931661ffff909616959095179190911716929092179091555183907f75c878cf35971786285583083fa747eac0e90af627ab5be381b17c8ddb38973690611881908490614066565b60405180910390a2505050565b6002546001600160a01b03163314806118b657503360009081526003602052604090205460ff165b6118d25760405162461bcd60e51b8152600401610ca090614040565b6000848152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b82048116958301869052600160a01b909104169281019290925260018101546060830152600281015460808301526003015461ffff811660a083015260ff6201000082048116151560c0840152630100000090910416151560e08201529103611980576040516347c0cce560e01b815260040160405180910390fd5b61ffff80851660a0830190815284151560c0840190815284151560e085019081526000898152600f60209081526040918290208751815492890151848a015163ffffffff908116600160a01b0263ffffffff60a01b1991909216600160801b026001600160a01b03199095166001600160801b03909316929092179390931716919091178155606087015160018201556080870151600282015593516003909401805493519251151563010000000263ff00000019931515620100000262ffffff19909516959096169490941792909217169290921790555185907fb132ee833b779c5596c27a38e7d120b7069d74aef3357175003558fa5314ca5d90611a88908490614066565b60405180910390a25050505050565b6002546001600160a01b0316331480611abf57503360009081526003602052604090205460ff165b611adb5760405162461bcd60e51b8152600401610ca090614040565b60086113d78282614248565b600a8054611082906140ec565b81600d5460ff1615611b0957611b0981612829565b611b138383612cf0565b505050565b6002546001600160a01b0316331480611b4057503360009081526003602052604090205460ff165b611b5c5760405162461bcd60e51b8152600401610ca090614040565b6113d78282612b85565b6000868152600f602090815260409182902082516101008101845281546001600160801b038116825263ffffffff600160801b8204811694830194909452600160a01b900490921692820192909252600182015460608201526002820154608082015260039091015461ffff811660a083015260ff6201000082048116151560c084015263010000009091041615801560e0830181905290611c135750611c11878787878787612d5c565b155b15611c3157604051638baa579f60e01b815260040160405180910390fd5b611c3e87878787856125b0565b50505050505050565b33600090815260208181526040808320858452909152902054811115611c9d5760405162461bcd60e51b815260206004820152600b60248201526a21a0a72727aa2fa12aa92760a91b6044820152606401610ca0565b6113d7338383612ef8565b6002546001600160a01b0316331480611cd057503360009081526003602052604090205460ff165b611cec5760405162461bcd60e51b8152600401610ca090614040565b600d805460ff1916911515919091179055565b6007546001600160a01b03163314611d685760405162461bcd60e51b815260206004820152602660248201527f4f6e6c7920746865206172746973742063616e2063616c6c20746869732066756044820152653731ba34b7b760d11b6064820152608401610ca0565b60105460ff1615611d8c57604051633c85668760e21b815260040160405180910390fd5b6003600052600f602090815260408051610100810182527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc8296828546001600160801b038116825263ffffffff600160801b8204811694830194909452600160a01b9004909216908201527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682954606082018181527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682a5460808401527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682b5461ffff811660a085015260ff6201000082048116151560c0860152630100000090910416151560e0840152601991611e9f908390614308565b90525060036000819052600f602090815282517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682880549285015160408601516001600160801b039093166001600160a01b031990941693909317600160801b63ffffffff948516021763ffffffff60a01b1916600160a01b939092169290920217905560608201517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc82968295560808201517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682a5560a08201517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682b805460c085015160e086015161ffff90941662ffffff199092169190911762010000911515919091021763ff00000019166301000000921515929092029190911790556010805460ff19166001179055600754612000916001600160a01b03909116906019612f6a565b6040516003907f97740a2d1e4e75b5dea30b31b96c67193bed444129f7f62010953c83c9b03dcd90600090a250565b6002546001600160a01b031633148061205757503360009081526003602052604090205460ff165b6120735760405162461bcd60e51b8152600401610ca090614040565b600e54612088906001600160a01b03166130f1565b600e60009054906101000a90046001600160a01b03166001600160a01b031663465105f06040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120d857600080fd5b505af11580156120ec573d6000803e3d6000fd5b50505050565b6000828152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b8204811683870152600160a01b9091041681840152600182015460608201526002820154608082015260039091015461ffff80821660a0840190815260ff6201000084048116151560c08601526301000000909304909216151560e08401526001600160a01b0387168652858552838620888752909452918420549151909284911682116121c557818360a0015161ffff166121c0919061431b565b6121c8565b60005b9695505050505050565b6002546001600160a01b03163314806121fa57503360009081526003602052604090205460ff165b6122165760405162461bcd60e51b8152600401610ca090614040565b600e54611576906001600160a01b03166130f1565b6002546001600160a01b031633148061225357503360009081526003602052604090205460ff165b61226f5760405162461bcd60e51b8152600401610ca090614040565b611436816131af565b6002546001600160a01b03163314806122a057503360009081526003602052604090205460ff165b6122bc5760405162461bcd60e51b8152600401610ca090614040565b6113d78282613224565b60088054611082906140ec565b6002546001600160a01b03163314806122fb57503360009081526003602052604090205460ff165b6123175760405162461bcd60e51b8152600401610ca090614040565b8163ffffffff1660000361233e576040516361bc7fb160e11b815260040160405180910390fd5b60008163ffffffff1611801561235957508063ffffffff1642115b156123775760405163312728dd60e11b815260040160405180910390fd5b6000838152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b82048116958301869052600160a01b909104169281019290925260018101546060830152600281015460808301526003015461ffff811660a083015260ff6201000082048116151560c0840152630100000090910416151560e08201529103612425576040516347c0cce560e01b815260040160405180910390fd5b63ffffffff808416602080840191825284831660408086019182526000898152600f9093529182902085518154945192518616600160a01b0263ffffffff60a01b1993909616600160801b026001600160a01b03199095166001600160801b03909116179390931716929092178155606083015160018201556080830151600282015560a08301516003909101805460c085015160e0860151151563010000000263ff00000019911515620100000262ffffff1990931661ffff9095169490941791909117169190911790555184907f4928d82a7d532bdf3025387660ebf504492c6a5eeb09af6d819dfc8fde01581590612521908490614066565b60405180910390a250505050565b856001600160a01b038116331461255457600d5460ff16156125545761255433612829565b611c3e8787878787876132a7565b60006301ffc9a760e01b6001600160e01b0319831614806125935750636cdb3d1360e11b6001600160e01b03198316145b80610fa95750506001600160e01b0319166303a24d0760e21b1490565b60008042836020015163ffffffff1611156125dd576040516254d81f60e41b815260040160405180910390fd5b6000836040015163ffffffff161180156126005750826040015163ffffffff1642115b1561261e576040516330aee1db60e21b815260040160405180910390fd5b341561263d57604051636992e1ff60e01b815260040160405180910390fd5b8260c00151801561265457506126528461348f565b155b1561267257604051633664886760e11b815260040160405180910390fd5b826060015160e11115801561268c57508260800151606411155b156126aa576040516352df9fe560e01b815260040160405180910390fd5b60808301516126ba90606461431b565b8511156126d85760808301516126d190606461431b565b90506126db565b50835b60608301516126eb9060e161431b565b8611156127095760608301516127029060e161431b565b915061270d565b8591505b60608301805183018152608084018051830181526000898152600f6020908152604080832088518154938a0151928a015163ffffffff908116600160a01b0263ffffffff60a01b1991909416600160801b026001600160a01b03199095166001600160801b03909216919091179390931792909216178155925160018401559051600283015560a08501516003909201805460c087015160e0880151151563010000000263ff00000019911515620100000262ffffff1990931661ffff909616959095179190911716929092179091556127e78284614308565b90506127f4858983612f6a565b60405188907f97740a2d1e4e75b5dea30b31b96c67193bed444129f7f62010953c83c9b03dcd90600090a25050505050505050565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa612865573d6000803e3d6000fd5b6000603a5250565b8483146128ae5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b6044820152606401610ca0565b336001600160a01b03891614806128e857506001600160a01b038816600090815260016020908152604080832033845290915290205460ff165b6129255760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610ca0565b60008060005b878110156129e057888882818110612945576129456141ec565b905060200201359250868682818110612960576129606141ec565b6001600160a01b038e166000908152602081815260408083208984528252822080549390910294909401359550859392509061299d90849061431b565b90915550506001600160a01b038a16600090815260208181526040808320868452909152812080548492906129d3908490614308565b909155505060010161292b565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b604051612a349493929190614360565b60405180910390a46001600160a01b0389163b15612adb5760405163bc197c8160e01b808252906001600160a01b038b169063bc197c8190612a889033908f908e908e908e908e908e908e906004016143bb565b6020604051808303816000875af1158015612aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acb919061441f565b6001600160e01b03191614612ae8565b6001600160a01b03891615155b612b045760405162461bcd60e51b8152600401610ca09061443c565b50505050505050505050565b6001600160a01b0390911690637d3e3dbe81612b3d5782612b365750634420e486612b3d565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af1612b7b578060005160e01c03612b7b57600080fd5b5060006024525050565b6001600160a01b038116612bac5760405163172fe2d160e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c179190614466565b905080600003612c3a5760405163334ab3f560e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390526000919085169063a9059cbb906044016020604051808303816000875af1158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb1919061447f565b9050806120ec57604051631d42c86760e21b815260040160405180910390fd5b611576733cc6cdda760b79bafa08df41ecfa224f810dceb66001612b10565b3360008181526001602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6000806040518060c00160405280898152602001888152602001878152602001866001600160a01b03168152602001600c6000886001600160a01b03166001600160a01b0316815260200190815260200160002054815260200185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525050825160208085015160408087015160608801516001600160a01b0381168752600c90945290852080549798509496612ea596507f3ebe2a8026435bce72f492f4f1687396bda15f10d2b8fe0db69d6dbaf7564a2b959293919288612e518361449c565b90915550604080516020810197909752860194909452606085019290925260808401526001600160a01b031660a083015260c082015260e001604051602081830303815290604052805190602001206134a2565b90506000612eb7828460a001516134f0565b6001600160a01b0381166000908152600b602052604090205490915060ff168015612eea57506001600160a01b03811615155b9a9950505050505050505050565b6001600160a01b03831660009081526020818152604080832085845290915281208054839290612f2990849061431b565b909155505060408051838152602081018390526000916001600160a01b038616913391600080516020614513833981519152910160405180910390a4505050565b6001600160a01b03831660009081526020818152604080832085845290915281208054839290612f9b908490614308565b909155505060075460408051848152602081018490526001600160a01b03909216916000913391600080516020614513833981519152910160405180910390a460075460408051848152602081018490526001600160a01b038681169316913391600080516020614513833981519152910160405180910390a46001600160a01b0383163b156130c85760075460405163f23a6e6160e01b8082523360048301526001600160a01b039283166024830152604482018590526064820184905260a06084830152600060a48301529185169063f23a6e619060c4016020604051808303816000875af1158015613094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b8919061441f565b6001600160e01b031916146130d5565b6001600160a01b03831615155b611b135760405162461bcd60e51b8152600401610ca09061443c565b6001600160a01b0381166131185760405163172fe2d160e01b815260040160405180910390fd5b47600081900361313b5760405163334ab3f560e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613188576040519150601f19603f3d011682016040523d82523d6000602084013e61318d565b606091505b5050905080611b1357604051631d42c86760e21b815260040160405180910390fd5b600554600160a01b900460ff16156131da576040516313ef243160e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040517f0713c9f4b0c5db294e61505e6819f6ad0cccf782df1a544939dc55d13fe7fc1c90600090a250565b612710811115613247576040516303c799a760e61b815260040160405180910390fd5b6040805180820182526001600160a01b03841680825262ffffff84166020909201829052600160a01b909102811760065590518291907ff21fccf4d64d86d532c4e4eb86c007b6ad57a460c27d724188625e755ec6cf6d90600090a35050565b336001600160a01b03871614806132e157506001600160a01b038616600090815260016020908152604080832033845290915290205460ff165b61331e5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610ca0565b6001600160a01b0386166000908152602081815260408083208784529091528120805485929061334f90849061431b565b90915550506001600160a01b03851660009081526020818152604080832087845290915281208054859290613385908490614308565b909155505060408051858152602081018590526001600160a01b0380881692908916913391600080516020614513833981519152910160405180910390a46001600160a01b0385163b1561345e5760405163f23a6e6160e01b808252906001600160a01b0387169063f23a6e619061340b9033908b908a908a908a908a906004016144b5565b6020604051808303816000875af115801561342a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061344e919061441f565b6001600160e01b0319161461346b565b6001600160a01b03851615155b6134875760405162461bcd60e51b8152600401610ca09061443c565b505050505050565b60008061349b83613514565b1192915050565b6000610fa96134af61358d565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006134ff85856136b4565b9150915061350c816136f9565b509392505050565b60048054604051627eeac760e11b81526001600160a01b0384811693820193909352600160248201526000929091169062fdd58e90604401602060405180830381865afa158015613569573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa99190614466565b6000306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480156135e657507f000000000000000000000000000000000000000000000000000000000000000046145b1561361057507f000000000000000000000000000000000000000000000000000000000000000090565b50604080517f00000000000000000000000000000000000000000000000000000000000000006020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60008082516041036136ea5760208301516040840151606085015160001a6136de87828585613843565b945094505050506136f2565b506000905060025b9250929050565b600081600481111561370d5761370d6144fc565b036137155750565b6001816004811115613729576137296144fc565b036137765760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610ca0565b600281600481111561378a5761378a6144fc565b036137d75760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610ca0565b60038160048111156137eb576137eb6144fc565b036114365760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610ca0565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561387a57506000905060036138fe565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156138ce573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166138f7576000600192509250506138fe565b9150600090505b94509492505050565b80356001600160801b038116811461391e57600080fd5b919050565b803563ffffffff8116811461391e57600080fd5b803561ffff8116811461391e57600080fd5b801515811461143657600080fd5b600080600080600080600060e0888a03121561397257600080fd5b8735965061398260208901613907565b955061399060408901613923565b945061399e60608901613923565b93506139ac60808901613937565b925060a08801356139bc81613949565b915060c08801356139cc81613949565b8091505092959891949750929550565b80356001600160a01b038116811461391e57600080fd5b60008060408385031215613a0657600080fd5b613a0f836139dc565b946020939093013593505050565b6001600160e01b03198116811461143657600080fd5b600060208284031215613a4557600080fd5b8135613a5081613a1d565b9392505050565b60008060008060808587031215613a6d57600080fd5b843593506020850135925060408501359150613a8b606086016139dc565b905092959194509250565b60005b83811015613ab1578181015183820152602001613a99565b50506000910152565b6020815260008251806020840152613ad9816040850160208701613a96565b601f01601f19169190910160400192915050565b600060208284031215613aff57600080fd5b5035919050565b600060208284031215613b1857600080fd5b613a50826139dc565b60008060408385031215613b3457600080fd5b50508035926020909101359150565b60008083601f840112613b5557600080fd5b50813567ffffffffffffffff811115613b6d57600080fd5b6020830191508360208260051b85010111156136f257600080fd5b60008083601f840112613b9a57600080fd5b50813567ffffffffffffffff811115613bb257600080fd5b6020830191508360208285010111156136f257600080fd5b60008060008060008060008060a0898b031215613be657600080fd5b613bef896139dc565b9750613bfd60208a016139dc565b9650604089013567ffffffffffffffff80821115613c1a57600080fd5b613c268c838d01613b43565b909850965060608b0135915080821115613c3f57600080fd5b613c4b8c838d01613b43565b909650945060808b0135915080821115613c6457600080fd5b50613c718b828c01613b88565b999c989b5096995094979396929594505050565b60008060408385031215613c9857600080fd5b613ca1836139dc565b91506020830135613cb181613949565b809150509250929050565b60008060008060408587031215613cd257600080fd5b843567ffffffffffffffff80821115613cea57600080fd5b613cf688838901613b43565b90965094506020870135915080821115613d0f57600080fd5b50613d1c87828801613b43565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b81811015613d6057835183529284019291840191600101613d44565b50909695505050505050565b60008060408385031215613d7f57600080fd5b823591506112d160208401613907565b60008060008060808587031215613da557600080fd5b84359350613db560208601613937565b92506040850135613dc581613949565b91506060850135613dd581613949565b939692955090935050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e1f57613e1f613de0565b604052919050565b600067ffffffffffffffff821115613e4157613e41613de0565b50601f01601f191660200190565b600060208284031215613e6157600080fd5b813567ffffffffffffffff811115613e7857600080fd5b8201601f81018413613e8957600080fd5b8035613e9c613e9782613e27565b613df6565b818152856020838501011115613eb157600080fd5b81602084016020830137600091810160200191909152949350505050565b60008060408385031215613ee257600080fd5b613eeb836139dc565b91506112d1602084016139dc565b60008060008060008060a08789031215613f1257600080fd5b863595506020870135945060408701359350613f30606088016139dc565b9250608087013567ffffffffffffffff811115613f4c57600080fd5b613f5889828a01613b88565b979a9699509497509295939492505050565b600060208284031215613f7c57600080fd5b8135613a5081613949565b60008060408385031215613f9a57600080fd5b823591506112d1602084016139dc565b600080600060608486031215613fbf57600080fd5b83359250613fcf60208501613923565b9150613fdd60408501613923565b90509250925092565b60008060008060008060a08789031215613fff57600080fd5b614008876139dc565b9550614016602088016139dc565b94506040870135935060608701359250608087013567ffffffffffffffff811115613f4c57600080fd5b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6000610100820190506001600160801b038351168252602083015163ffffffff80821660208501528060408601511660408501525050606083015160608301526080830151608083015261ffff60a08401511660a083015260c08301516140d160c084018215159052565b5060e08301516140e560e084018215159052565b5092915050565b600181811c9082168061410057607f821691505b60208210810361412057634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561413857600080fd5b815167ffffffffffffffff81111561414f57600080fd5b8201601f8101841361416057600080fd5b805161416e613e9782613e27565b81815285602083850101111561418357600080fd5b614194826020830160208601613a96565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610fa957610fa961419d565b6000826141e757634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b601f821115611b1357600081815260208120601f850160051c810160208610156142295750805b601f850160051c820191505b8181101561348757828155600101614235565b815167ffffffffffffffff81111561426257614262613de0565b6142768161427084546140ec565b84614202565b602080601f8311600181146142ab57600084156142935750858301515b600019600386901b1c1916600185901b178555613487565b600085815260208120601f198616915b828110156142da578886015182559484019460019091019084016142bb565b50858210156142f85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115610fa957610fa961419d565b81810381811115610fa957610fa961419d565b81835260006001600160fb1b0383111561434757600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061437460408301868861432e565b828103602084015261438781858761432e565b979650505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0389811682528816602082015260a0604082018190526000906143e8908301888a61432e565b82810360608401526143fb81878961432e565b90508281036080840152614410818587614392565b9b9a5050505050505050505050565b60006020828403121561443157600080fd5b8151613a5081613a1d565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b60006020828403121561447857600080fd5b5051919050565b60006020828403121561449157600080fd5b8151613a5081613949565b6000600182016144ae576144ae61419d565b5060010190565b6001600160a01b03878116825286166020820152604081018590526060810184905260a0608082018190526000906144f09083018486614392565b98975050505050505050565b634e487b7160e01b600052602160045260246000fdfec3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62a164736f6c6343000811000a0000000000000000000000003b1bd4c99c059ed58155240fd01d6fc86a430d4d0000000000000000000000006306d0cdfadd6095a313e8484275b6cc7036166c00000000000000000000000085056ddc1b6e64e9afb6e662b503b1b5c3cdecad00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000069442276c71df2de463b7b3d170f427a8dd26e0a00000000000000000000000016f444f2d9e696834c1c9b536dc3896e1b545213
Deployed Bytecode
0x6080604052600436106103955760003560e01c8063881ced95116101dc578063c0fd735b11610102578063e2e784d5116100a0578063ecd8dbf71161006f578063ecd8dbf714610bc8578063f242432a14610be8578063fb796e6c14610c08578063fd6724fc14610c2257600080fd5b8063e2e784d514610b18578063e3faad9414610b38578063e8a3d48514610b78578063e985e9c514610b8d57600080fd5b8063de7ff469116100dc578063de7ff46914610aa9578063df27092014610ac9578063e086e5ec14610ae3578063e17b25af14610af857600080fd5b8063c0fd735b14610a3d578063d4ddce8a14610a52578063d7e45cd714610a8857600080fd5b8063a41572961161017a578063b05fc5cc11610149578063b05fc5cc146109d5578063b390c0ab146109e8578063b7c0b8e814610a08578063c01c3c9c14610a2857600080fd5b8063a415729614610934578063a522ad2514610961578063a6d23e1014610981578063af4fddfa146109a157600080fd5b80638da5cb5b116101b65780638da5cb5b146108bf578063938e3d7b146108df57806395d89b41146108ff578063a22cb4651461091457600080fd5b8063881ced951461083557806389d020dc1461086f5780638a8755121461088f57600080fd5b806343bc1612116102c157806358a478ed1161025f578063704802751161022e57806370480275146107b35780637c1a8343146107d35780637ecebe00146107f35780637f20256a1461082057600080fd5b806358a478ed146107145780635e1c0746146107445780635e1e1004146107595780636b2a9d251461077957600080fd5b806349df728c1161029b57806349df728c146106825780634d820b4f146106a25780634e1273f4146106d2578063582e8ae5146106ff57600080fd5b806343bc16121461060e578063453722411461062e57806346d8efad1461066257600080fd5b80631785f53c1161033957806331cb61051161030857806331cb610514610561578063392f37e9146105815780633fc8cef3146105b9578063429b62e5146105de57600080fd5b80631785f53c146104a957806326645a2c146104c95780632a55205a146105025780632eb2c2d61461054157600080fd5b80630651efa3116103755780630651efa31461043457806306fdde03146104475780630e89341c1461046957806313af40351461048957600080fd5b8062029eb81461039a578062fdd58e146103bc57806301ffc9a714610404575b600080fd5b3480156103a657600080fd5b506103ba6103b5366004613957565b610c5c565b005b3480156103c857600080fd5b506103f16103d73660046139f3565b600060208181529281526040808220909352908152205481565b6040519081526020015b60405180910390f35b34801561041057600080fd5b5061042461041f366004613a33565b610f84565b60405190151581526020016103fb565b6103ba610442366004613a57565b610faf565b34801561045357600080fd5b5061045c611075565b6040516103fb9190613aba565b34801561047557600080fd5b5061045c610484366004613aed565b611103565b34801561049557600080fd5b506103ba6104a4366004613b06565b611175565b3480156104b557600080fd5b506103ba6104c4366004613b06565b611205565b3480156104d557600080fd5b506104246104e4366004613aed565b6000908152600f602052604090206003015462010000900460ff1690565b34801561050e57600080fd5b5061052261051d366004613b21565b611293565b604080516001600160a01b0390931683526020830191909152016103fb565b34801561054d57600080fd5b506103ba61055c366004613bca565b6112da565b34801561056d57600080fd5b506103ba61057c366004613c85565b61131a565b34801561058d57600080fd5b506005546105a1906001600160a01b031681565b6040516001600160a01b0390911681526020016103fb565b3480156105c557600080fd5b50600d546105a19061010090046001600160a01b031681565b3480156105ea57600080fd5b506104246105f9366004613b06565b60036020526000908152604090205460ff1681565b34801561061a57600080fd5b506007546105a1906001600160a01b031681565b34801561063a57600080fd5b506103f1610649366004613aed565b6000908152600f602052604090206003015461ffff1690565b34801561066e57600080fd5b506103ba61067d366004613c85565b611389565b34801561068e57600080fd5b506103ba61069d366004613b06565b6113db565b3480156106ae57600080fd5b506103f16106bd366004613aed565b6000908152600f602052604090206002015490565b3480156106de57600080fd5b506106f26106ed366004613cbc565b611439565b6040516103fb9190613d28565b34801561070b57600080fd5b506103f160e181565b34801561072057600080fd5b506103f161072f366004613aed565b6000908152600f602052604090206001015490565b34801561075057600080fd5b506103ba61156e565b34801561076557600080fd5b506103ba610774366004613b06565b611578565b34801561078557600080fd5b50610424610794366004613aed565b6000908152600f60205260409020600301546301000000900460ff1690565b3480156107bf57600080fd5b506103ba6107ce366004613b06565b611605565b3480156107df57600080fd5b506103ba6107ee366004613d6c565b611696565b3480156107ff57600080fd5b506103f161080e366004613b06565b600c6020526000908152604090205481565b34801561082c57600080fd5b506103f1606481565b34801561084157600080fd5b506103f1610850366004613aed565b6000908152600f6020526040902054600160801b900463ffffffff1690565b34801561087b57600080fd5b506103ba61088a366004613d8f565b61188e565b34801561089b57600080fd5b506104246108aa366004613b06565b600b6020526000908152604090205460ff1681565b3480156108cb57600080fd5b506002546105a1906001600160a01b031681565b3480156108eb57600080fd5b506103ba6108fa366004613e4f565b611a97565b34801561090b57600080fd5b5061045c611ae7565b34801561092057600080fd5b506103ba61092f366004613c85565b611af4565b34801561094057600080fd5b5061045c604051806040016040528060018152602001603160f81b81525081565b34801561096d57600080fd5b506103ba61097c366004613ecf565b611b18565b34801561098d57600080fd5b50600e546105a1906001600160a01b031681565b3480156109ad57600080fd5b506103f17f3ebe2a8026435bce72f492f4f1687396bda15f10d2b8fe0db69d6dbaf7564a2b81565b6103ba6109e3366004613ef9565b611b66565b3480156109f457600080fd5b506103ba610a03366004613b21565b611c47565b348015610a1457600080fd5b506103ba610a23366004613f6a565b611ca8565b348015610a3457600080fd5b506103ba611cff565b348015610a4957600080fd5b506103ba61202f565b348015610a5e57600080fd5b506103f1610a6d366004613aed565b6000908152600f60205260409020546001600160801b031690565b348015610a9457600080fd5b5060055461042490600160a01b900460ff1681565b348015610ab557600080fd5b506103f1610ac4366004613f87565b6120f2565b348015610ad557600080fd5b506010546104249060ff1681565b348015610aef57600080fd5b506103ba6121d2565b348015610b0457600080fd5b506103ba610b13366004613b06565b61222b565b348015610b2457600080fd5b506103ba610b333660046139f3565b612278565b348015610b4457600080fd5b5061045c604051806040016040528060148152602001734d6f726e696e67734f70656e45646974696f6e7360601b81525081565b348015610b8457600080fd5b5061045c6122c6565b348015610b9957600080fd5b50610424610ba8366004613ecf565b600160209081526000928352604080842090915290825290205460ff1681565b348015610bd457600080fd5b506103ba610be3366004613faa565b6122d3565b348015610bf457600080fd5b506103ba610c03366004613fe6565b61252f565b348015610c1457600080fd5b50600d546104249060ff1681565b348015610c2e57600080fd5b506103f1610c3d366004613aed565b6000908152600f6020526040902054600160a01b900463ffffffff1690565b6002546001600160a01b0316331480610c8457503360009081526003602052604090205460ff165b610ca95760405162461bcd60e51b8152600401610ca090614040565b60405180910390fd5b8463ffffffff16600003610cd0576040516361bc7fb160e11b815260040160405180910390fd5b60008463ffffffff16118015610ceb57508363ffffffff1642115b15610d095760405163312728dd60e11b815260040160405180910390fd5b6000878152600f602090815260409182902082516101008101845281546001600160801b038116825263ffffffff600160801b82048116948301859052600160a01b909104169381019390935260018101546060840152600281015460808401526003015461ffff811660a084015260ff6201000082048116151560c0850152630100000090910416151560e083015215610db7576040516320705a1b60e11b815260040160405180910390fd5b8681600001906001600160801b031690816001600160801b03168152505085816020019063ffffffff16908163ffffffff168152505084816040019063ffffffff16908163ffffffff1681525050838160a0019061ffff16908161ffff1681525050828160c0019015159081151581525050818160e001901515908115158152505080600f60008a815260200190815260200160002060008201518160000160006101000a8154816001600160801b0302191690836001600160801b0316021790555060208201518160000160106101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160146101000a81548163ffffffff021916908363ffffffff160217905550606082015181600101556080820151816002015560a08201518160030160006101000a81548161ffff021916908361ffff16021790555060c08201518160030160026101000a81548160ff02191690831515021790555060e08201518160030160036101000a81548160ff021916908315150217905550905050877f14eb4bf6c7d72fc73e72c7352fc7607a0ac11969cadce90af77c0540a7b0c33082604051610f729190614066565b60405180910390a25050505050505050565b60006001600160e01b0319821663152a902d60e11b1480610fa95750610fa982612562565b92915050565b6000848152600f602090815260409182902082516101008101845281546001600160801b038116825263ffffffff600160801b8204811694830194909452600160a01b900490921692820192909252600182015460608201526002820154608082015260039091015461ffff811660a083015260ff6201000082048116151560c084015263010000009091041615801560e083015261106157604051630426ff7760e01b815260040160405180910390fd5b61106e85858585856125b0565b5050505050565b60098054611082906140ec565b80601f01602080910402602001604051908101604052809291908181526020018280546110ae906140ec565b80156110fb5780601f106110d0576101008083540402835291602001916110fb565b820191906000526020600020905b8154815290600101906020018083116110de57829003601f168201915b505050505081565b60055460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd90602401600060405180830381865afa15801561114d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610fa99190810190614126565b6002546001600160a01b031633148061119d57503360009081526003602052604090205460ff165b6111b95760405162461bcd60e51b8152600401610ca090614040565b600280546001600160a01b0319166001600160a01b03831690811790915560405133907f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d7690600090a350565b6002546001600160a01b031633148061122d57503360009081526003602052604090205460ff165b6112495760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b038116600081815260036020526040808220805460ff19169055517fdb9d5d31320daf5bc7181d565b6da4d12e30f0f4d5aa324a992426c14a1d19ce908290a350565b6006546001600160a01b03811690600090612710906112c790600160a01b90046bffffffffffffffffffffffff16856141b3565b6112d191906141ca565b90509250929050565b876001600160a01b03811633146112ff57600d5460ff16156112ff576112ff33612829565b61130f898989898989898961286d565b505050505050505050565b6002546001600160a01b031633148061134257503360009081526003602052604090205460ff165b61135e5760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b03919091166000908152600b60205260409020805460ff1916911515919091179055565b6002546001600160a01b03163314806113b157503360009081526003602052604090205460ff165b6113cd5760405162461bcd60e51b8152600401610ca090614040565b6113d78282612b10565b5050565b6002546001600160a01b031633148061140357503360009081526003602052604090205460ff165b61141f5760405162461bcd60e51b8152600401610ca090614040565b600e546114369082906001600160a01b0316612b85565b50565b606083821461147c5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b6044820152606401610ca0565b8367ffffffffffffffff81111561149557611495613de0565b6040519080825280602002602001820160405280156114be578160200160208202803683370190505b50905060005b84811015611565576000808787848181106114e1576114e16141ec565b90506020020160208101906114f69190613b06565b6001600160a01b03166001600160a01b03168152602001908152602001600020600085858481811061152a5761152a6141ec565b90506020020135815260200190815260200160002054828281518110611552576115526141ec565b60209081029190910101526001016114c4565b50949350505050565b611576612cd1565b565b6002546001600160a01b03163314806115a057503360009081526003602052604090205460ff165b6115bc5760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b0381166115e357604051631f4c499760e01b815260040160405180910390fd5b600e80546001600160a01b0319166001600160a01b0392909216919091179055565b6002546001600160a01b031633148061162d57503360009081526003602052604090205460ff165b6116495760405162461bcd60e51b8152600401610ca090614040565b6001600160a01b038116600081815260036020526040808220805460ff19166001179055517fbf3f493c772c8c283fd124432c2d0f539ab343faa04258fe88e52912d36b102b908290a350565b6002546001600160a01b03163314806116be57503360009081526003602052604090205460ff165b6116da5760405162461bcd60e51b8152600401610ca090614040565b6000828152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b82048116958301869052600160a01b909104169281019290925260018101546060830152600281015460808301526003015461ffff811660a083015260ff6201000082048116151560c0840152630100000090910416151560e08201529103611788576040516347c0cce560e01b815260040160405180910390fd5b6001600160801b0380831682526000848152600f602090815260409182902084518154928601518487015163ffffffff908116600160a01b0263ffffffff60a01b1991909216600160801b026001600160a01b031990951692909616919091179290921793909316178255606083015160018301556080830151600283015560a08301516003909201805460c085015160e0860151151563010000000263ff00000019911515620100000262ffffff1990931661ffff909616959095179190911716929092179091555183907f75c878cf35971786285583083fa747eac0e90af627ab5be381b17c8ddb38973690611881908490614066565b60405180910390a2505050565b6002546001600160a01b03163314806118b657503360009081526003602052604090205460ff165b6118d25760405162461bcd60e51b8152600401610ca090614040565b6000848152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b82048116958301869052600160a01b909104169281019290925260018101546060830152600281015460808301526003015461ffff811660a083015260ff6201000082048116151560c0840152630100000090910416151560e08201529103611980576040516347c0cce560e01b815260040160405180910390fd5b61ffff80851660a0830190815284151560c0840190815284151560e085019081526000898152600f60209081526040918290208751815492890151848a015163ffffffff908116600160a01b0263ffffffff60a01b1991909216600160801b026001600160a01b03199095166001600160801b03909316929092179390931716919091178155606087015160018201556080870151600282015593516003909401805493519251151563010000000263ff00000019931515620100000262ffffff19909516959096169490941792909217169290921790555185907fb132ee833b779c5596c27a38e7d120b7069d74aef3357175003558fa5314ca5d90611a88908490614066565b60405180910390a25050505050565b6002546001600160a01b0316331480611abf57503360009081526003602052604090205460ff165b611adb5760405162461bcd60e51b8152600401610ca090614040565b60086113d78282614248565b600a8054611082906140ec565b81600d5460ff1615611b0957611b0981612829565b611b138383612cf0565b505050565b6002546001600160a01b0316331480611b4057503360009081526003602052604090205460ff165b611b5c5760405162461bcd60e51b8152600401610ca090614040565b6113d78282612b85565b6000868152600f602090815260409182902082516101008101845281546001600160801b038116825263ffffffff600160801b8204811694830194909452600160a01b900490921692820192909252600182015460608201526002820154608082015260039091015461ffff811660a083015260ff6201000082048116151560c084015263010000009091041615801560e0830181905290611c135750611c11878787878787612d5c565b155b15611c3157604051638baa579f60e01b815260040160405180910390fd5b611c3e87878787856125b0565b50505050505050565b33600090815260208181526040808320858452909152902054811115611c9d5760405162461bcd60e51b815260206004820152600b60248201526a21a0a72727aa2fa12aa92760a91b6044820152606401610ca0565b6113d7338383612ef8565b6002546001600160a01b0316331480611cd057503360009081526003602052604090205460ff165b611cec5760405162461bcd60e51b8152600401610ca090614040565b600d805460ff1916911515919091179055565b6007546001600160a01b03163314611d685760405162461bcd60e51b815260206004820152602660248201527f4f6e6c7920746865206172746973742063616e2063616c6c20746869732066756044820152653731ba34b7b760d11b6064820152608401610ca0565b60105460ff1615611d8c57604051633c85668760e21b815260040160405180910390fd5b6003600052600f602090815260408051610100810182527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc8296828546001600160801b038116825263ffffffff600160801b8204811694830194909452600160a01b9004909216908201527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682954606082018181527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682a5460808401527f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682b5461ffff811660a085015260ff6201000082048116151560c0860152630100000090910416151560e0840152601991611e9f908390614308565b90525060036000819052600f602090815282517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682880549285015160408601516001600160801b039093166001600160a01b031990941693909317600160801b63ffffffff948516021763ffffffff60a01b1916600160a01b939092169290920217905560608201517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc82968295560808201517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682a5560a08201517f45f76dafbbad695564362934e24d72eedc57f9fc1a65f39bca62176cc829682b805460c085015160e086015161ffff90941662ffffff199092169190911762010000911515919091021763ff00000019166301000000921515929092029190911790556010805460ff19166001179055600754612000916001600160a01b03909116906019612f6a565b6040516003907f97740a2d1e4e75b5dea30b31b96c67193bed444129f7f62010953c83c9b03dcd90600090a250565b6002546001600160a01b031633148061205757503360009081526003602052604090205460ff165b6120735760405162461bcd60e51b8152600401610ca090614040565b600e54612088906001600160a01b03166130f1565b600e60009054906101000a90046001600160a01b03166001600160a01b031663465105f06040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120d857600080fd5b505af11580156120ec573d6000803e3d6000fd5b50505050565b6000828152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b8204811683870152600160a01b9091041681840152600182015460608201526002820154608082015260039091015461ffff80821660a0840190815260ff6201000084048116151560c08601526301000000909304909216151560e08401526001600160a01b0387168652858552838620888752909452918420549151909284911682116121c557818360a0015161ffff166121c0919061431b565b6121c8565b60005b9695505050505050565b6002546001600160a01b03163314806121fa57503360009081526003602052604090205460ff165b6122165760405162461bcd60e51b8152600401610ca090614040565b600e54611576906001600160a01b03166130f1565b6002546001600160a01b031633148061225357503360009081526003602052604090205460ff165b61226f5760405162461bcd60e51b8152600401610ca090614040565b611436816131af565b6002546001600160a01b03163314806122a057503360009081526003602052604090205460ff165b6122bc5760405162461bcd60e51b8152600401610ca090614040565b6113d78282613224565b60088054611082906140ec565b6002546001600160a01b03163314806122fb57503360009081526003602052604090205460ff165b6123175760405162461bcd60e51b8152600401610ca090614040565b8163ffffffff1660000361233e576040516361bc7fb160e11b815260040160405180910390fd5b60008163ffffffff1611801561235957508063ffffffff1642115b156123775760405163312728dd60e11b815260040160405180910390fd5b6000838152600f6020908152604080832081516101008101835281546001600160801b038116825263ffffffff600160801b82048116958301869052600160a01b909104169281019290925260018101546060830152600281015460808301526003015461ffff811660a083015260ff6201000082048116151560c0840152630100000090910416151560e08201529103612425576040516347c0cce560e01b815260040160405180910390fd5b63ffffffff808416602080840191825284831660408086019182526000898152600f9093529182902085518154945192518616600160a01b0263ffffffff60a01b1993909616600160801b026001600160a01b03199095166001600160801b03909116179390931716929092178155606083015160018201556080830151600282015560a08301516003909101805460c085015160e0860151151563010000000263ff00000019911515620100000262ffffff1990931661ffff9095169490941791909117169190911790555184907f4928d82a7d532bdf3025387660ebf504492c6a5eeb09af6d819dfc8fde01581590612521908490614066565b60405180910390a250505050565b856001600160a01b038116331461255457600d5460ff16156125545761255433612829565b611c3e8787878787876132a7565b60006301ffc9a760e01b6001600160e01b0319831614806125935750636cdb3d1360e11b6001600160e01b03198316145b80610fa95750506001600160e01b0319166303a24d0760e21b1490565b60008042836020015163ffffffff1611156125dd576040516254d81f60e41b815260040160405180910390fd5b6000836040015163ffffffff161180156126005750826040015163ffffffff1642115b1561261e576040516330aee1db60e21b815260040160405180910390fd5b341561263d57604051636992e1ff60e01b815260040160405180910390fd5b8260c00151801561265457506126528461348f565b155b1561267257604051633664886760e11b815260040160405180910390fd5b826060015160e11115801561268c57508260800151606411155b156126aa576040516352df9fe560e01b815260040160405180910390fd5b60808301516126ba90606461431b565b8511156126d85760808301516126d190606461431b565b90506126db565b50835b60608301516126eb9060e161431b565b8611156127095760608301516127029060e161431b565b915061270d565b8591505b60608301805183018152608084018051830181526000898152600f6020908152604080832088518154938a0151928a015163ffffffff908116600160a01b0263ffffffff60a01b1991909416600160801b026001600160a01b03199095166001600160801b03909216919091179390931792909216178155925160018401559051600283015560a08501516003909201805460c087015160e0880151151563010000000263ff00000019911515620100000262ffffff1990931661ffff909616959095179190911716929092179091556127e78284614308565b90506127f4858983612f6a565b60405188907f97740a2d1e4e75b5dea30b31b96c67193bed444129f7f62010953c83c9b03dcd90600090a25050505050505050565b69c617113400112233445560005230601a5280603a52600080604460166daaeb6d7670e522a718067333cd4e5afa612865573d6000803e3d6000fd5b6000603a5250565b8483146128ae5760405162461bcd60e51b815260206004820152600f60248201526e0988a9c8ea890be9a92a69a82a8869608b1b6044820152606401610ca0565b336001600160a01b03891614806128e857506001600160a01b038816600090815260016020908152604080832033845290915290205460ff165b6129255760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610ca0565b60008060005b878110156129e057888882818110612945576129456141ec565b905060200201359250868682818110612960576129606141ec565b6001600160a01b038e166000908152602081815260408083208984528252822080549390910294909401359550859392509061299d90849061431b565b90915550506001600160a01b038a16600090815260208181526040808320868452909152812080548492906129d3908490614308565b909155505060010161292b565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b604051612a349493929190614360565b60405180910390a46001600160a01b0389163b15612adb5760405163bc197c8160e01b808252906001600160a01b038b169063bc197c8190612a889033908f908e908e908e908e908e908e906004016143bb565b6020604051808303816000875af1158015612aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612acb919061441f565b6001600160e01b03191614612ae8565b6001600160a01b03891615155b612b045760405162461bcd60e51b8152600401610ca09061443c565b50505050505050505050565b6001600160a01b0390911690637d3e3dbe81612b3d5782612b365750634420e486612b3d565b5063a0af29035b8060e01b60005230600452826024526004600060446000806daaeb6d7670e522a718067333cd4e5af1612b7b578060005160e01c03612b7b57600080fd5b5060006024525050565b6001600160a01b038116612bac5760405163172fe2d160e01b815260040160405180910390fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015612bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c179190614466565b905080600003612c3a5760405163334ab3f560e11b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390526000919085169063a9059cbb906044016020604051808303816000875af1158015612c8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cb1919061447f565b9050806120ec57604051631d42c86760e21b815260040160405180910390fd5b611576733cc6cdda760b79bafa08df41ecfa224f810dceb66001612b10565b3360008181526001602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6000806040518060c00160405280898152602001888152602001878152602001866001600160a01b03168152602001600c6000886001600160a01b03166001600160a01b0316815260200190815260200160002054815260200185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250939094525050825160208085015160408087015160608801516001600160a01b0381168752600c90945290852080549798509496612ea596507f3ebe2a8026435bce72f492f4f1687396bda15f10d2b8fe0db69d6dbaf7564a2b959293919288612e518361449c565b90915550604080516020810197909752860194909452606085019290925260808401526001600160a01b031660a083015260c082015260e001604051602081830303815290604052805190602001206134a2565b90506000612eb7828460a001516134f0565b6001600160a01b0381166000908152600b602052604090205490915060ff168015612eea57506001600160a01b03811615155b9a9950505050505050505050565b6001600160a01b03831660009081526020818152604080832085845290915281208054839290612f2990849061431b565b909155505060408051838152602081018390526000916001600160a01b038616913391600080516020614513833981519152910160405180910390a4505050565b6001600160a01b03831660009081526020818152604080832085845290915281208054839290612f9b908490614308565b909155505060075460408051848152602081018490526001600160a01b03909216916000913391600080516020614513833981519152910160405180910390a460075460408051848152602081018490526001600160a01b038681169316913391600080516020614513833981519152910160405180910390a46001600160a01b0383163b156130c85760075460405163f23a6e6160e01b8082523360048301526001600160a01b039283166024830152604482018590526064820184905260a06084830152600060a48301529185169063f23a6e619060c4016020604051808303816000875af1158015613094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b8919061441f565b6001600160e01b031916146130d5565b6001600160a01b03831615155b611b135760405162461bcd60e51b8152600401610ca09061443c565b6001600160a01b0381166131185760405163172fe2d160e01b815260040160405180910390fd5b47600081900361313b5760405163334ab3f560e11b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613188576040519150601f19603f3d011682016040523d82523d6000602084013e61318d565b606091505b5050905080611b1357604051631d42c86760e21b815260040160405180910390fd5b600554600160a01b900460ff16156131da576040516313ef243160e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040517f0713c9f4b0c5db294e61505e6819f6ad0cccf782df1a544939dc55d13fe7fc1c90600090a250565b612710811115613247576040516303c799a760e61b815260040160405180910390fd5b6040805180820182526001600160a01b03841680825262ffffff84166020909201829052600160a01b909102811760065590518291907ff21fccf4d64d86d532c4e4eb86c007b6ad57a460c27d724188625e755ec6cf6d90600090a35050565b336001600160a01b03871614806132e157506001600160a01b038616600090815260016020908152604080832033845290915290205460ff165b61331e5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606401610ca0565b6001600160a01b0386166000908152602081815260408083208784529091528120805485929061334f90849061431b565b90915550506001600160a01b03851660009081526020818152604080832087845290915281208054859290613385908490614308565b909155505060408051858152602081018590526001600160a01b0380881692908916913391600080516020614513833981519152910160405180910390a46001600160a01b0385163b1561345e5760405163f23a6e6160e01b808252906001600160a01b0387169063f23a6e619061340b9033908b908a908a908a908a906004016144b5565b6020604051808303816000875af115801561342a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061344e919061441f565b6001600160e01b0319161461346b565b6001600160a01b03851615155b6134875760405162461bcd60e51b8152600401610ca09061443c565b505050505050565b60008061349b83613514565b1192915050565b6000610fa96134af61358d565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b60008060006134ff85856136b4565b9150915061350c816136f9565b509392505050565b60048054604051627eeac760e11b81526001600160a01b0384811693820193909352600160248201526000929091169062fdd58e90604401602060405180830381865afa158015613569573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa99190614466565b6000306001600160a01b037f000000000000000000000000663e218f49edffdb838131f1f2fda255f593206d161480156135e657507f000000000000000000000000000000000000000000000000000000000000000146145b1561361057507f7801042e2ef91426e891f70220f66ffcd199bd3b77bae53e1bcd2d4fb9053b6190565b50604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fad862c941698014fb2bfd67682e111f44f4d73d146cbeddc6f77eb4e40f02bff828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b60008082516041036136ea5760208301516040840151606085015160001a6136de87828585613843565b945094505050506136f2565b506000905060025b9250929050565b600081600481111561370d5761370d6144fc565b036137155750565b6001816004811115613729576137296144fc565b036137765760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610ca0565b600281600481111561378a5761378a6144fc565b036137d75760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610ca0565b60038160048111156137eb576137eb6144fc565b036114365760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610ca0565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561387a57506000905060036138fe565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156138ce573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166138f7576000600192509250506138fe565b9150600090505b94509492505050565b80356001600160801b038116811461391e57600080fd5b919050565b803563ffffffff8116811461391e57600080fd5b803561ffff8116811461391e57600080fd5b801515811461143657600080fd5b600080600080600080600060e0888a03121561397257600080fd5b8735965061398260208901613907565b955061399060408901613923565b945061399e60608901613923565b93506139ac60808901613937565b925060a08801356139bc81613949565b915060c08801356139cc81613949565b8091505092959891949750929550565b80356001600160a01b038116811461391e57600080fd5b60008060408385031215613a0657600080fd5b613a0f836139dc565b946020939093013593505050565b6001600160e01b03198116811461143657600080fd5b600060208284031215613a4557600080fd5b8135613a5081613a1d565b9392505050565b60008060008060808587031215613a6d57600080fd5b843593506020850135925060408501359150613a8b606086016139dc565b905092959194509250565b60005b83811015613ab1578181015183820152602001613a99565b50506000910152565b6020815260008251806020840152613ad9816040850160208701613a96565b601f01601f19169190910160400192915050565b600060208284031215613aff57600080fd5b5035919050565b600060208284031215613b1857600080fd5b613a50826139dc565b60008060408385031215613b3457600080fd5b50508035926020909101359150565b60008083601f840112613b5557600080fd5b50813567ffffffffffffffff811115613b6d57600080fd5b6020830191508360208260051b85010111156136f257600080fd5b60008083601f840112613b9a57600080fd5b50813567ffffffffffffffff811115613bb257600080fd5b6020830191508360208285010111156136f257600080fd5b60008060008060008060008060a0898b031215613be657600080fd5b613bef896139dc565b9750613bfd60208a016139dc565b9650604089013567ffffffffffffffff80821115613c1a57600080fd5b613c268c838d01613b43565b909850965060608b0135915080821115613c3f57600080fd5b613c4b8c838d01613b43565b909650945060808b0135915080821115613c6457600080fd5b50613c718b828c01613b88565b999c989b5096995094979396929594505050565b60008060408385031215613c9857600080fd5b613ca1836139dc565b91506020830135613cb181613949565b809150509250929050565b60008060008060408587031215613cd257600080fd5b843567ffffffffffffffff80821115613cea57600080fd5b613cf688838901613b43565b90965094506020870135915080821115613d0f57600080fd5b50613d1c87828801613b43565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b81811015613d6057835183529284019291840191600101613d44565b50909695505050505050565b60008060408385031215613d7f57600080fd5b823591506112d160208401613907565b60008060008060808587031215613da557600080fd5b84359350613db560208601613937565b92506040850135613dc581613949565b91506060850135613dd581613949565b939692955090935050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715613e1f57613e1f613de0565b604052919050565b600067ffffffffffffffff821115613e4157613e41613de0565b50601f01601f191660200190565b600060208284031215613e6157600080fd5b813567ffffffffffffffff811115613e7857600080fd5b8201601f81018413613e8957600080fd5b8035613e9c613e9782613e27565b613df6565b818152856020838501011115613eb157600080fd5b81602084016020830137600091810160200191909152949350505050565b60008060408385031215613ee257600080fd5b613eeb836139dc565b91506112d1602084016139dc565b60008060008060008060a08789031215613f1257600080fd5b863595506020870135945060408701359350613f30606088016139dc565b9250608087013567ffffffffffffffff811115613f4c57600080fd5b613f5889828a01613b88565b979a9699509497509295939492505050565b600060208284031215613f7c57600080fd5b8135613a5081613949565b60008060408385031215613f9a57600080fd5b823591506112d1602084016139dc565b600080600060608486031215613fbf57600080fd5b83359250613fcf60208501613923565b9150613fdd60408501613923565b90509250925092565b60008060008060008060a08789031215613fff57600080fd5b614008876139dc565b9550614016602088016139dc565b94506040870135935060608701359250608087013567ffffffffffffffff811115613f4c57600080fd5b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b6000610100820190506001600160801b038351168252602083015163ffffffff80821660208501528060408601511660408501525050606083015160608301526080830151608083015261ffff60a08401511660a083015260c08301516140d160c084018215159052565b5060e08301516140e560e084018215159052565b5092915050565b600181811c9082168061410057607f821691505b60208210810361412057634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561413857600080fd5b815167ffffffffffffffff81111561414f57600080fd5b8201601f8101841361416057600080fd5b805161416e613e9782613e27565b81815285602083850101111561418357600080fd5b614194826020830160208601613a96565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610fa957610fa961419d565b6000826141e757634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b601f821115611b1357600081815260208120601f850160051c810160208610156142295750805b601f850160051c820191505b8181101561348757828155600101614235565b815167ffffffffffffffff81111561426257614262613de0565b6142768161427084546140ec565b84614202565b602080601f8311600181146142ab57600084156142935750858301515b600019600386901b1c1916600185901b178555613487565b600085815260208120601f198616915b828110156142da578886015182559484019460019091019084016142bb565b50858210156142f85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820180821115610fa957610fa961419d565b81810381811115610fa957610fa961419d565b81835260006001600160fb1b0383111561434757600080fd5b8260051b80836020870137939093016020019392505050565b60408152600061437460408301868861432e565b828103602084015261438781858761432e565b979650505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0389811682528816602082015260a0604082018190526000906143e8908301888a61432e565b82810360608401526143fb81878961432e565b90508281036080840152614410818587614392565b9b9a5050505050505050505050565b60006020828403121561443157600080fd5b8151613a5081613a1d565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b60006020828403121561447857600080fd5b5051919050565b60006020828403121561449157600080fd5b8151613a5081613949565b6000600182016144ae576144ae61419d565b5060010190565b6001600160a01b03878116825286166020820152604081018590526060810184905260a0608082018190526000906144f09083018486614392565b98975050505050505050565b634e487b7160e01b600052602160045260246000fdfec3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62a164736f6c6343000811000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003b1bd4c99c059ed58155240fd01d6fc86a430d4d0000000000000000000000006306d0cdfadd6095a313e8484275b6cc7036166c00000000000000000000000085056ddc1b6e64e9afb6e662b503b1b5c3cdecad00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000069442276c71df2de463b7b3d170f427a8dd26e0a00000000000000000000000016f444f2d9e696834c1c9b536dc3896e1b545213
-----Decoded View---------------
Arg [0] : owner_ (address): 0x3B1Bd4C99c059ED58155240FD01D6fC86A430D4D
Arg [1] : admin_ (address): 0x6306D0cDFADD6095A313e8484275b6cC7036166C
Arg [2] : payments_ (address): 0x85056DdC1B6e64e9AfB6E662B503b1B5C3CDEcad
Arg [3] : royaltiesAmount_ (uint256): 750
Arg [4] : metadata_ (address): 0x69442276C71DF2de463b7B3d170F427a8dD26E0a
Arg [5] : fountCard_ (address): 0x16F444F2d9E696834C1c9b536Dc3896E1B545213
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000003b1bd4c99c059ed58155240fd01d6fc86a430d4d
Arg [1] : 0000000000000000000000006306d0cdfadd6095a313e8484275b6cc7036166c
Arg [2] : 00000000000000000000000085056ddc1b6e64e9afb6e662b503b1b5c3cdecad
Arg [3] : 00000000000000000000000000000000000000000000000000000000000002ee
Arg [4] : 00000000000000000000000069442276c71df2de463b7b3d170f427a8dd26e0a
Arg [5] : 00000000000000000000000016f444f2d9e696834c1c9b536dc3896e1b545213
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.