Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 18963473 | 197 days ago | IN | Create: ERC721LA | 0 ETH | 0.12911575 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ERC721LA
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../extensions/Burnable.sol"; import "../extensions/WithOperatorRegistry.sol"; import "../extensions/AirDropable.sol"; import "./IERC721LA.sol"; import "../extensions/Pausable.sol"; import "../extensions/Whitelistable.sol"; // import "../extensions/PermissionedTransfers.sol"; import "../extensions/LAInitializable.sol"; import "../libraries/LANFTUtils.sol"; import "../libraries/BPS.sol"; import "../libraries/CustomErrors.sol"; import "../platform/royalties/RoyaltiesState.sol"; import "./ERC721State.sol"; import "./ERC721LACore.sol"; /** * @notice LiveArt ERC721 implementation contract * Supports multiple edtioned NFTs and gas optimized batch minting */ contract ERC721LA is ERC721LACore, Burnable, AirDropable, Whitelistable { /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Royalties * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function setRoyaltyRegistryAddress( address _royaltyRegistry ) public onlyAdmin { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._royaltyRegistry = IRoyaltiesRegistry(_royaltyRegistry); } function royaltyRegistryAddress() public view returns (IRoyaltiesRegistry) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._royaltyRegistry; } /// @dev see: EIP-2981 function royaltyInfo( uint256 _tokenId, uint256 _value ) external view returns (address _receiver, uint256 _royaltyAmount) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._royaltyRegistry.royaltyInfo(address(this), _tokenId, _value); } function registerCollectionRoyaltyReceivers( RoyaltiesState.RoyaltyReceiver[] memory royaltyReceivers ) public onlyAdmin { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); IRoyaltiesRegistry(state._royaltyRegistry) .registerCollectionRoyaltyReceivers( address(this), msg.sender, royaltyReceivers ); } function primaryRoyaltyInfo( uint256 tokenId ) public view returns (address payable[] memory, uint256[] memory) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return IRoyaltiesRegistry(state._royaltyRegistry).primaryRoyaltyInfo( address(this), tokenId ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// 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: UNLICENSED pragma solidity ^0.8.4; import "./IAccessControl.sol"; abstract contract AccessControl is IAccessControl{ bytes32 public constant COLLECTION_ADMIN_ROLE = keccak256("COLLECTION_ADMIN_ROLE"); function _getAccessControlState() internal pure returns (RoleState storage state) { bytes32 position = keccak256("liveart.AccessControl"); assembly { state.slot := position } } /** * @notice Checks that msg.sender has a specific role. * Reverts with a AccessControlNotAllowed. * */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @notice Checks that msg.sender has COLLECTION_ADMIN_ROLE * Reverts with a AccessControlNotAllowed. * */ modifier onlyAdmin() { _checkRole(COLLECTION_ADMIN_ROLE); _; } function isAdmin(address theAddress) public view returns (bool) { return hasRole(COLLECTION_ADMIN_ROLE, theAddress); } /** * @notice Checks if role is assigned to account * */ function hasRole(bytes32 role, address account) public view returns (bool) { RoleState storage state = _getAccessControlState(); return state._roles[role][account]; } /** * @notice Revert with a AccessControlNotAllowed message if `msg.sender` is missing `role`. * */ function _checkRole(bytes32 role) internal view virtual { if (!hasRole(role, msg.sender)) { revert AccessControlNotAllowed(); } } /** * @notice Grants `role` to `account`. * * @dev If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) public onlyAdmin { _grantRole(role, account); } /** * @notice Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have COLLECTION_ADMIN_ROLE role. */ function revokeRole(bytes32 role, address account) public onlyAdmin { _revokeRole(role, account); } /** * @notice Revokes `role` from the calling account. * * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) public virtual { if (account != msg.sender) { revert AccessControlNotAllowed(); } _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. */ function _grantRole(bytes32 role, address account) internal { RoleState storage state = _getAccessControlState(); if (!hasRole(role, account)) { state._roles[role][account] = true; emit RoleGranted(role, account, msg.sender); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. */ function _revokeRole(bytes32 role, address account) internal { RoleState storage state = _getAccessControlState(); if (hasRole(role, account)) { state._roles[role][account] = false; emit RoleRevoked(role, account, msg.sender); } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../libraries/CustomErrors.sol"; import "../libraries/BPS.sol"; import "../libraries/CustomErrors.sol"; import "../libraries/LANFTUtils.sol"; import "../tokens/ERC721State.sol"; import "../tokens/ERC721LACore.sol"; import "./IAirDropable.sol"; import "../platform/royalties/RoyaltiesState.sol"; abstract contract AirDropable is IAirDropable, ERC721LACore { uint256 public constant AIRDROP_MAX_BATCH_SIZE = 100; function airdrop( uint256 editionId, address[] calldata recipients, uint24 quantityPerAddress ) external onlyAdmin { if (recipients.length > AIRDROP_MAX_BATCH_SIZE) { revert TooManyAddresses(); } for (uint256 i = 0; i < recipients.length; i++) { _safeMint(editionId, quantityPerAddress, recipients[i]); } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../libraries/CustomErrors.sol"; import "../libraries/BPS.sol"; import "../tokens/ERC721LACore.sol"; import "../libraries/LANFTUtils.sol"; import "../tokens/ERC721State.sol"; abstract contract Burnable is ERC721LACore { /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * BURNABLE * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function burn(uint256 tokenId) public { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); address owner = ownerOf(tokenId); if (!_isApprovedOrOwner(msg.sender, tokenId)) { revert CustomErrors.TransferError(); } _transferCore(owner, ERC721LACore.burnAddress, tokenId); // Looksrare and other marketplace require the owner to be null address emit Transfer(owner, address(0), tokenId); (uint256 editionId, ) = parseEditionFromTokenId(tokenId); // Update the number of tokens burned for this edition state._editions[editionId].burnedSupply += 1; } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * @param tokenIds array of tokenIds to burn * Requirements: * - `tokenId` must exist. * Emits a {Transfer} event. */ function burnMultiple(uint256[] calldata tokenIds) public { for (uint i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; burn(tokenId); } } function burnRedeemEditionTokens( uint256 _editionId, uint24 _quantity, uint256[] calldata tokenIdsToBurn ) public whenPublicMintOpened(_editionId) whenNotPaused { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); ERC721State.Edition memory edition = getEdition(_editionId); if (edition.burnableEditionId == 0 || tokenIdsToBurn.length == 0) { revert CustomErrors.BurnRedeemNotAvailable(); } uint256 mintableAmount = tokenIdsToBurn.length / edition.amountToBurn; if (mintableAmount < _quantity) { revert CustomErrors.BurnRedeemNotAvailable(); } // Check max mint per wallet restrictions (if maxMintPerWallet is 0, no restriction apply) uint256 mintedCountKey = uint256( keccak256(abi.encodePacked(_editionId, msg.sender)) ); if (edition.maxMintPerWallet != 0) { if ( state._mintedPerWallet[mintedCountKey] + _quantity > edition.maxMintPerWallet ) { revert CustomErrors.MaximumMintAmountReached(); } } state._mintedPerWallet[mintedCountKey] += _quantity; // We iterate and burn only the required amount of tokens (preventing burning more than necessary) // burn will revert if the sender is not the owner of a given token for (uint256 i; i < edition.amountToBurn * _quantity; i++) { burn(tokenIdsToBurn[i]); } _safeMint(_editionId, _quantity, msg.sender); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; interface IAccessControl { error AccessControlNotAllowed(); struct RoleState { mapping(bytes32 => mapping(address => bool)) _roles; } /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role */ event RoleGranted( bytes32 indexed role, address indexed account, address indexed sender ); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked( bytes32 indexed role, address indexed account, address indexed sender ); /** * @notice Checks if role is assigned to account * */ function hasRole(bytes32 role, address account) external returns (bool); /** * @notice Grants `role` to `account`. * * @dev If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @notice Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have COLLECTION_ADMIN_ROLE role. */ function revokeRole(bytes32 role, address account) external; /** * @notice Revokes `role` from the calling account. * * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; function isAdmin(address theAddress) external view returns (bool); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; interface IAirDropable { error TooManyAddresses(); function airdrop(uint256 editionId, address[] calldata recipients, uint24 quantityPerAddres) external; }
/// @title EIP-721 Metadata Update Extension interface IERC4906 { /// @dev This event emits when the metadata of a token is changed. /// So that the third-party platforms such as NFT market could /// timely update the images and related attributes of the NFT. event MetadataUpdate(uint256 _tokenId); /// @dev This event emits when the metadata of a range of tokens is changed. /// So that the third-party platforms such as NFT market could /// timely update the images and related attributes of the NFTs. event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; interface IWhitelistable { /** * Raised when trying create a WhiteList config that already exisit (mint amounts are the same) */ error WhiteListAlreadyExists(); error NotWhitelisted(); error InvalidMintDuration(); function whitelistMint( uint256 editionId, uint8 maxAmount, uint24 mintPriceInFinney, bytes32[] calldata merkleProof, uint24 quantity, address receiver, uint24 tokenId, uint24 mintPriceWithPrintInFinney ) external payable; function setWLConfig( uint256 editionId, uint8 amount, uint24 mintPriceInFinney, uint32 mintStartTS, uint32 mintEndTS, bytes32 merkleRoot, uint24 mintPriceWithPrintInFinney ) external; function updateWLConfig( uint256 editionId, uint8 amount, uint24 mintPriceInFinney, uint8 newAmount, uint24 newMintPriceInFinney, uint32 newMintStartTS, uint32 newMintEndTS, bytes32 newMerkleRoot, uint24 mintPriceWithPrintInFinney, uint24 newMintPriceWithPrintInFinney ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; abstract contract LAInitializable { error AlreadyInitialized(); struct InitializableState { bool _initialized; } function _getInitializableState() internal pure returns (InitializableState storage state) { bytes32 position = keccak256("liveart.Initializable"); assembly { state.slot := position } } modifier notInitialized() { InitializableState storage state = _getInitializableState(); if (state._initialized) { revert AlreadyInitialized(); } _; state._initialized = true; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; abstract contract Ownable { error CallerIsNotOwner(); error NewOwnerIsZeroAddress(); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); struct OwnableState { address owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } function owner() public view returns(address){ OwnableState storage state = _getOwnableState(); return state.owner; } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if(newOwner == address(0)){ revert NewOwnerIsZeroAddress(); } _transferOwnership(newOwner); } function _getOwnableState() internal pure returns (OwnableState storage state) { bytes32 position = keccak256("liveart.Ownable"); assembly { state.slot := position } } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if(owner() != msg.sender) { revert CallerIsNotOwner(); } } function _setOwner(address newOwner) internal { OwnableState storage state = _getOwnableState(); state.owner = newOwner; } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal { address previousOwner = owner(); _setOwner(newOwner); emit OwnershipTransferred(previousOwner, newOwner); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ contract Pausable { event Paused(address account); event Unpaused(address account); struct PausableState { bool _paused; } function _getPausableState() internal pure returns (PausableState storage state) { bytes32 position = keccak256("liveart.Pausable"); assembly { state.slot := position } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * MODIFIERS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view returns (bool) { PausableState storage state = _getPausableState(); return state._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal whenNotPaused { PausableState storage state = _getPausableState(); state._paused = true; emit Paused(msg.sender); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal whenPaused { PausableState storage state = _getPausableState(); state._paused = false; emit Unpaused(msg.sender); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../libraries/BPS.sol"; import "../libraries/CustomErrors.sol"; import "../libraries/LANFTUtils.sol"; import "../tokens/ERC721State.sol"; import "../tokens/ERC721LACore.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "./IWhitelistable.sol"; import "./WhitelistableState.sol"; interface ILiveArtXcard { function balanceOf(address owner) external view returns (uint256); } abstract contract Whitelistable is IWhitelistable, ERC721LACore { /** * Create a Whitelist configuration * @param _editionId the edition ID * @param amount How many mint allowed per Whitelist spot * @param mintPriceInFinney Price of the whitelist mint in Finney * @param mintStartTS Starting time of the Whitelist mint * @param mintEndTS Starting time of the Whitelist mint * @param merkleRoot The whitelist merkle root * @param mintPriceWithPrintInFinney The mint price with print in Finney * */ function setWLConfig( uint256 _editionId, uint8 amount, uint24 mintPriceInFinney, uint32 mintStartTS, uint32 mintEndTS, bytes32 merkleRoot, uint24 mintPriceWithPrintInFinney ) public onlyAdmin { WhitelistableState.WLState storage state = WhitelistableState ._getWhitelistableState(); // This reverts if edition does not exist getEdition(_editionId); uint256 wlId = uint256( keccak256( abi.encodePacked( _editionId, amount, mintPriceInFinney, mintPriceWithPrintInFinney ) ) ); if (state._whitelistConfig[wlId].amount != 0) { revert WhiteListAlreadyExists(); } if (mintEndTS != 0 && mintEndTS < mintStartTS) { revert InvalidMintDuration(); } WhitelistableState.WhitelistConfig memory whitelistConfig = WhitelistableState.WhitelistConfig({ merkleRoot: merkleRoot, amount: amount, mintPriceInFinney: mintPriceInFinney, mintStartTS: mintStartTS, mintEndTS: mintEndTS, mintPriceWithPrintInFinney: mintPriceWithPrintInFinney }); state._whitelistConfig[wlId] = whitelistConfig; } /** * Update a Whitelist configuration * @param _editionId Edition ID of the WL to be updated * @param _amount Amount of the WL to be updated * @param mintPriceInFinney Price of the WL to be updated * @param newAmount New Amount * @param newMintPriceInFinney New mint price in Finney * @param newMintStartTS New Mint time * @param newMerkleRoot New Merkle root * * Note: When changing a single property of the WL config, * make sure to also pass the value of the property that did not change. * */ function updateWLConfig( uint256 _editionId, uint8 _amount, uint24 mintPriceInFinney, uint8 newAmount, uint24 newMintPriceInFinney, uint32 newMintStartTS, uint32 newMintEndTS, bytes32 newMerkleRoot, uint24 mintPriceWithPrintInFinney, uint24 newMintPriceWithPrintInFinney ) public onlyAdmin { WhitelistableState.WLState storage state = WhitelistableState ._getWhitelistableState(); // This reverts if edition does not exist getEdition(_editionId); uint256 wlId = uint256( keccak256( abi.encodePacked( _editionId, _amount, mintPriceInFinney, mintPriceWithPrintInFinney ) ) ); WhitelistableState.WhitelistConfig memory whitelistConfig; // If amount or price differ, then set previous WL config key to amount 0, which effectively disable the WL if ( _amount != newAmount || mintPriceInFinney != newMintPriceInFinney || mintPriceWithPrintInFinney != newMintPriceWithPrintInFinney ) { state._whitelistConfig[wlId] = WhitelistableState.WhitelistConfig({ merkleRoot: newMerkleRoot, amount: 0, mintPriceInFinney: newMintPriceInFinney, mintStartTS: newMintStartTS, mintEndTS: newMintEndTS, mintPriceWithPrintInFinney: newMintPriceWithPrintInFinney }); wlId = uint256( keccak256( abi.encodePacked( _editionId, newAmount, newMintPriceInFinney, newMintPriceWithPrintInFinney ) ) ); state._whitelistConfig[wlId] = whitelistConfig; } if (newMintEndTS != 0 && newMintEndTS < newMintStartTS) { revert InvalidMintDuration(); } whitelistConfig = WhitelistableState.WhitelistConfig({ merkleRoot: newMerkleRoot, amount: newAmount, mintPriceInFinney: newMintPriceInFinney, mintStartTS: newMintStartTS, mintEndTS: newMintEndTS, mintPriceWithPrintInFinney: newMintPriceWithPrintInFinney }); state._whitelistConfig[wlId] = whitelistConfig; } /** * Whitelist mint function * @param _editionId the edition ID * @param _maxAmount How many mint allowed per Whitelist spot * @param _merkleProof the merkle proof of the minter * @param _quantity How many NFTs to mint * @param _recipient The recipient of the NFTs * @param _xCardTokenId The XCard token ID * @param _mintPriceWithPrintInFinney The mint price with print in Finney */ function whitelistMint( uint256 _editionId, uint8 _maxAmount, uint24 _mintPriceInFinney, bytes32[] calldata _merkleProof, uint24 _quantity, address _recipient, uint24 _xCardTokenId, uint24 _mintPriceWithPrintInFinney ) public payable { _validateWhitelistMintingParameters( _editionId, _maxAmount, _mintPriceInFinney, _merkleProof, _quantity, _mintPriceWithPrintInFinney ); _validateMintPrice(_mintPriceInFinney, _quantity); uint256 firstTokenId = _safeMint(_editionId, _quantity, _recipient); _sendRoyaltiesAfterMint(firstTokenId); } /** * Whitelist mint with print function * @param _editionId the edition ID * @param _maxAmount How many mint allowed per Whitelist spot * @param _merkleProof the merkle proof of the minter * @param _quantity How many NFTs to mint * @param _recipient The recipient of the NFTs * @param _xCardTokenId The XCard token ID * @param _mintPriceWithPrintInFinney The mint price with print in Finney */ function whitelistMintWithPrint( uint256 _editionId, uint8 _maxAmount, uint24 _mintPriceInFinney, bytes32[] calldata _merkleProof, uint24 _quantity, address _recipient, uint24 _xCardTokenId, uint24 _mintPriceWithPrintInFinney ) public payable { ERC721State.EditionWithPrintData memory printData = getEditionPrintData( _editionId ); _validateWhitelistMintingParameters( _editionId, _maxAmount, _mintPriceInFinney, _merkleProof, _quantity, _mintPriceWithPrintInFinney ); _validateEditionPrintData(printData); _validateMintPrice(_mintPriceWithPrintInFinney, _quantity); uint256 firstTokenId = _safeMint(_editionId, _quantity, _recipient); _sendRoyaltiesAfterMint(firstTokenId); _mintPrintVouchers(_editionId, _quantity, firstTokenId); } /** * Get WL config for given editionId, amout, and mintPrice. * Should not be used internally when trying to modify the state as it returns a memory copy of the structs */ function getWLConfig( uint256 editionId, uint8 amount, uint24 mintPriceInFinney, uint24 mintPriceWithPrintInFinney ) public view returns (WhitelistableState.WhitelistConfig memory) { WhitelistableState.WLState storage state = WhitelistableState ._getWhitelistableState(); // This reverts if edition does not exist getEdition(editionId); uint256 wlId = uint256( keccak256( abi.encodePacked( editionId, amount, mintPriceInFinney, mintPriceWithPrintInFinney ) ) ); WhitelistableState.WhitelistConfig storage whitelistConfig = state ._whitelistConfig[wlId]; if (whitelistConfig.amount == 0) { revert CustomErrors.NotFound(); } return whitelistConfig; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INTERNAL FUNCTIONS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function _validateWhitelistMintingParameters( uint256 _editionId, uint8 maxAmount, uint24 mintPriceInFinney, bytes32[] calldata merkleProof, uint24 _quantity, uint24 mintPriceWithPrintInFinney ) internal { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); // This reverts if WL does not exist (or is disabled) WhitelistableState.WhitelistConfig memory whitelistConfig = getWLConfig( _editionId, maxAmount, mintPriceInFinney, mintPriceWithPrintInFinney ); // Check for allowed mint count uint256 mintCountKey = uint256( keccak256(abi.encodePacked(_editionId, msg.sender)) ); if ( state._mintedPerWallet[mintCountKey] + _quantity > whitelistConfig.amount ) { revert CustomErrors.MaximumMintAmountReached(); } if ( whitelistConfig.mintStartTS == 0 || block.timestamp < whitelistConfig.mintStartTS ) { revert CustomErrors.MintClosed(); } if ( whitelistConfig.mintEndTS != 0 && block.timestamp > whitelistConfig.mintEndTS ) { revert CustomErrors.MintClosed(); } // We use msg.sender for the WL merkle root // Ran only if the user is not an XCard holder bytes32 leaf = keccak256(abi.encodePacked(msg.sender)); if ( !MerkleProof.verify( merkleProof, whitelistConfig.merkleRoot, leaf ) && ILiveArtXcard(state._xCardContractAddress).balanceOf(msg.sender) == 0 ) { revert NotWhitelisted(); } state._mintedPerWallet[mintCountKey] += _quantity; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; library WhitelistableState { struct WhitelistConfig { bytes32 merkleRoot; uint8 amount; uint24 mintPriceInFinney; uint32 mintStartTS; uint32 mintEndTS; uint24 mintPriceWithPrintInFinney; } struct WLState { // hash(EditionId + mintable amount + price) mapping(uint256 => WhitelistConfig) _whitelistConfig; } /** * @dev Get storage data from dedicated slot. * This pattern avoids storage conflict during proxy upgrades * and give more flexibility when creating extensions */ function _getWhitelistableState() internal pure returns (WLState storage state) { bytes32 storageSlot = keccak256("liveart.Whitelistable"); assembly { state.slot := storageSlot } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../extensions/AccessControl.sol"; /** * Used to set Winter whitelisted minting addresses */ contract Winter is AccessControl { struct WinterState { address[] winterAddresses; } function _getWinterState() internal pure returns (WinterState storage state) { bytes32 position = keccak256("liveart.Winter"); assembly { state.slot := position } } // function addWinterWallets(address[] calldata newAddresses) public onlyAdmin { // for(uint256 i; i < newAddresses.length; i += 1) { // _setWinterWallet(newAddresses[i]); // } // } function addWinterWallet(address newAddress) public onlyAdmin { _setWinterWallet(newAddress); } function _setWinterWallet(address newAddress) internal { WinterState storage state = _getWinterState(); state.winterAddresses.push(newAddress); } function deleteWinterWallet(address newAddress) public onlyAdmin { WinterState storage state = _getWinterState(); for (uint256 i; i < state.winterAddresses.length; i += 1) { if (newAddress == state.winterAddresses[i]) { delete state.winterAddresses[i]; } } state.winterAddresses.push(newAddress); } function _isWinterWallet() internal view returns (bool) { WinterState storage state = _getWinterState(); for (uint256 i; i < state.winterAddresses.length; i += 1) { if (msg.sender == state.winterAddresses[i]) { return true; } } return false; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../libraries/CustomErrors.sol"; import "./WithOperatorRegistryState.sol"; import "../libraries/LANFTUtils.sol"; import "../extensions/AccessControl.sol"; import "operator-filter-registry/src/IOperatorFilterRegistry.sol"; import {CANONICAL_CORI_SUBSCRIPTION} from "operator-filter-registry/src/lib/Constants.sol"; contract WithOperatorRegistry is AccessControl { address constant DEFAULT_OPERATOR_REGISTRY_ADDRESS = 0x000000000000AAeB6D7670E522A718067333cd4E; /// @dev The upgradeable initialize function that should be called when the contract is being upgraded. function _initOperatorRegsitry() internal { WithOperatorRegistryState.OperatorRegistryState storage registryState = WithOperatorRegistryState ._getOperatorRegistryState(); IOperatorFilterRegistry registry = IOperatorFilterRegistry( DEFAULT_OPERATOR_REGISTRY_ADDRESS ); registryState.operatorFilterRegistry = registry; if (address(registry).code.length > 0) { registry.registerAndSubscribe( address(this), CANONICAL_CORI_SUBSCRIPTION ); } } function initOperatorRegsitry() public onlyAdmin { _initOperatorRegsitry(); } /** * @dev A helper modifier to check if the operator is allowed. */ modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != msg.sender) { _checkFilterOperator(msg.sender); } _; } /** * @dev A helper modifier to check if the operator approval is allowed. */ modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } /** * @dev A helper function to check if the operator is allowed. */ function _checkFilterOperator(address operator) internal view virtual { WithOperatorRegistryState.OperatorRegistryState storage registryState = WithOperatorRegistryState ._getOperatorRegistryState(); // Check registry code length to facilitate testing in environments without a deployed registry. if (address(registryState.operatorFilterRegistry).code.length > 0) { // under normal circumstances, this function will revert rather than return false, but inheriting or // upgraded contracts may specify their own OperatorFilterRegistry implementations, which may behave // differently if ( !registryState.operatorFilterRegistry.isOperatorAllowed( address(this), operator ) ) { revert CustomErrors.NotAllowed(); } } } /** * @notice Update the address that the contract will make OperatorFilter checks against. When set to the zero * address, checks will be bypassed. OnlyOwner. */ function updateOperatorFilterRegistryAddress(address newRegistry) public onlyAdmin { WithOperatorRegistryState.OperatorRegistryState storage registryState = WithOperatorRegistryState ._getOperatorRegistryState(); IOperatorFilterRegistry registry = IOperatorFilterRegistry( newRegistry ); registryState.operatorFilterRegistry = registry; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "operator-filter-registry/src/IOperatorFilterRegistry.sol"; library WithOperatorRegistryState { struct OperatorRegistryState { IOperatorFilterRegistry operatorFilterRegistry; } /** * @dev Get storage data from dedicated slot. * This pattern avoids storage conflict during proxy upgrades * and give more flexibility when creating extensions */ function _getOperatorRegistryState() internal pure returns (OperatorRegistryState storage state) { bytes32 storageSlot = keccak256("liveart.OperatorRegistryState"); assembly { state.slot := storageSlot } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "./BitScan.sol"; /** * Derived from: https://github.com/estarriolvetch/solidity-bits */ /** * @dev This Library is a modified version of Openzeppelin's BitMaps library. * Functions of finding the index of the closest set bit from a given index are added. * The indexing of each bucket is modifed to count from the MSB to the LSB instead of from the LSB to the MSB. * The modification of indexing makes finding the closest previous set bit more efficient in gas usage. */ /** * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential. * Largelly inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. */ error BitMapHeadNotFound(); library BitMaps { using BitScan for uint256; uint256 private constant MASK_INDEX_ZERO = (1 << 255); struct BitMap { mapping(uint256 => uint256) _data; } /** * @dev Returns whether the bit at `index` is set. */ function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { uint256 bucket = index >> 8; uint256 mask = MASK_INDEX_ZERO >> (index & 0xff); return bitmap._data[bucket] & mask != 0; } /** * @dev Sets the bit at `index` to the boolean `value`. */ function setTo( BitMap storage bitmap, uint256 index, bool value ) internal { if (value) { set(bitmap, index); } else { unset(bitmap, index); } } /** * @dev Sets the bit at `index`. */ function set(BitMap storage bitmap, uint256 index) internal { uint256 bucket = index >> 8; uint256 mask = MASK_INDEX_ZERO >> (index & 0xff); bitmap._data[bucket] |= mask; } /** * @dev Unsets the bit at `index`. */ function unset(BitMap storage bitmap, uint256 index) internal { uint256 bucket = index >> 8; uint256 mask = MASK_INDEX_ZERO >> (index & 0xff); bitmap._data[bucket] &= ~mask; } /** * @dev Find the closest index of the set bit before `index`. */ function scanForward( BitMap storage bitmap, uint256 index, uint256 lowerBound ) internal view returns (uint256 matchedIndex) { uint256 bucket = index >> 8; uint256 lowerBoundBucket = lowerBound >> 8; // index within the bucket uint256 bucketIndex = (index & 0xff); // load a bitboard from the bitmap. uint256 bb = bitmap._data[bucket]; // offset the bitboard to scan from `bucketIndex`. bb = bb >> (0xff ^ bucketIndex); // bb >> (255 - bucketIndex) if (bb > 0) { unchecked { return (bucket << 8) | (bucketIndex - bb.bitScanForward256()); } } else { while (true) { // require(bucket > lowerBound, "BitMaps: The set bit before the index doesn't exist."); if (bucket < lowerBoundBucket) { revert BitMapHeadNotFound(); } unchecked { bucket--; } // No offset. Always scan from the least significiant bit now. bb = bitmap._data[bucket]; if (bb > 0) { unchecked { return (bucket << 8) | (255 - bb.bitScanForward256()); } } } } } }
// SPDX-License-Identifier: UNLICENSED /** _____ ___ ___ __ ____ _ __ / ___/____ / (_)___/ (_) /___ __ / __ )(_) /______ \__ \/ __ \/ / / __ / / __/ / / / / __ / / __/ ___/ ___/ / /_/ / / / /_/ / / /_/ /_/ / / /_/ / / /_(__ ) /____/\____/_/_/\__,_/_/\__/\__, / /_____/_/\__/____/ /____/ - npm: https://www.npmjs.com/package/solidity-bits - github: https://github.com/estarriolvetch/solidity-bits */ pragma solidity ^0.8.4; library BitScan { uint256 constant private DEBRUIJN_256 = 0x818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff; bytes constant private LOOKUP_TABLE_256 = hex"0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8"; /** @dev Isolate the least significant set bit. */ function isolateLS1B256(uint256 bb) pure internal returns (uint256) { require(bb > 0); unchecked { return bb & (0 - bb); } } /** @dev Isolate the most significant set bit. */ function isolateMS1B256(uint256 bb) pure internal returns (uint256) { require(bb > 0); unchecked { bb |= bb >> 256; bb |= bb >> 128; bb |= bb >> 64; bb |= bb >> 32; bb |= bb >> 16; bb |= bb >> 8; bb |= bb >> 4; bb |= bb >> 2; bb |= bb >> 1; return (bb >> 1) + 1; } } /** @dev Find the index of the lest significant set bit. (trailing zero count) */ function bitScanForward256(uint256 bb) pure internal returns (uint8) { unchecked { return uint8(LOOKUP_TABLE_256[(isolateLS1B256(bb) * DEBRUIJN_256) >> 248]); } } /** @dev Find the index of the most significant set bit. */ function bitScanReverse256(uint256 bb) pure internal returns (uint8) { unchecked { return 255 - uint8(LOOKUP_TABLE_256[((isolateMS1B256(bb) * DEBRUIJN_256) >> 248)]); } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; library BPS { function _calculatePercentage(uint256 number, uint256 percentage) internal pure returns (uint256) { // https://ethereum.stackexchange.com/a/55702 // https://www.investopedia.com/terms/b/basispoint.asp return (number * percentage) / 10000; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; library CustomErrors { /** * Raised when trying to manipulate editions (CRUD) with invalid data */ error InvalidEditionData(); error MaxSupplyError(); error InvalidEditionId(); /** * Raised when trying to mint with invalid data */ error InvalidMintData(); /** * Raised when trying to transfer an NFT to a non ERC721Receiver */ error NotERC721Receiver(); /** * Raised when trying to query a non minted token */ error TokenNotFound(); /** * Raised when transfer fail */ error TransferError(); /** * Generic Not Allowed action */ error NotAllowed(); /** * Generic Not Found error */ error NotFound(); /** * Raised when direct minting with insufficient funds */ error InsufficientFunds(); /** * Raised when fund transfer fails */ error FundTransferError(); /** * Raised when trying to mint a print with invalid data */ error InvalidPrintData(); error MintClosed(); error MaximumMintAmountReached(); error BurnRedeemNotAvailable(); error NotXCardOwner(); error TokenStaked(); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "./CustomErrors.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; library LANFTUtils { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is an EOA * */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) internal returns (bool) { if (LANFTUtils.isContract(to)) { try IERC721Receiver(to).onERC721Received( msg.sender, from, tokenId, _data ) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert CustomErrors.NotERC721Receiver(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "./specs/IRarible.sol"; import "./RoyaltiesState.sol"; /// @dev Royalty registry interface interface IRoyaltiesRegistry is IERC165 { /// @dev Raised when trying to set a royalty override for a token error NotApproved(); error NotOwner(); /// @dev Raised when providing multiple royalty overrides when only one is expected error MultipleRoyaltyRecievers(); /// @dev Raised when sales percentage is not between 0 and 100 error PrimarySalePercentageOutOfRange(); error SecondarySalePercentageOutOfRange(); /// @dev Raised accumulated primary royalty percentage is not 100 error PrimarySalePercentageNotEqualToMax(); /** * Raised trying to set edition or token royalties */ error NotEditionCreator(); // ============================== // EVENTS // ============================== event RoyaltyOverride( address owner, address tokenAddress, address royaltyAddress ); event RoyaltyTokenOverride( address owner, address tokenAddress, uint256 tokenId, address royaltyAddress ); // ============================== // IERC165 // ============================== /// @dev See {IERC165-supportsInterface}. function supportsInterface( bytes4 interfaceId ) external view override returns (bool); // ============================== // SECONDARY ROYALTY // ============================== /* @notice Called with the sale price to determine how much royalty is owed and to whom. @param _contractAddress - The collection address @param _tokenId - the NFT asset queried for royalty information @param _value - the sale price of the NFT asset specified by _tokenId @return _receiver - address of who should be sent the royalty payment @return _royaltyAmount - the royalty payment amount for value sale price */ function royaltyInfo( address _contractAddress, uint256 _tokenId, uint256 _value ) external view returns (address _receiver, uint256 _royaltyAmount); /** * Return RoyaltyReceivers for primary sales * */ function primaryRoyaltyInfo( address collectionAddress, uint256 tokenId ) external view returns (address payable[] memory, uint256[] memory); /** * @dev CreatorCore - Supports Manifold, ArtBlocks * * getRoyalties */ function getRoyalties( address collectionAddress, uint256 tokenId ) external view returns (address payable[] memory, uint256[] memory); /** * @dev Foundation * * getFees */ function getFees( address collectionAddress, uint256 editionId ) external view returns (address payable[] memory, uint256[] memory); /** * @dev Rarible: RoyaltiesV1 * * getFeeBps */ function getFeeBps( address collectionAddress, uint256 tokenId ) external view returns (uint256[] memory); /** * @dev Rarible: RoyaltiesV1 * * getFeeRecipients */ function getFeeRecipients( address collectionAddress, uint256 editionId ) external view returns (address payable[] memory); /** * @dev Rarible: RoyaltiesV2 * * getRaribleV2Royalties */ function getRaribleV2Royalties( address collectionAddress, uint256 tokenId ) external view returns (IRaribleV2.Part[] memory); /** * @dev CreatorCore - Support for KODA * * getKODAV2RoyaltyInfo */ function getKODAV2RoyaltyInfo( address collectionAddress, uint256 tokenId ) external view returns (address payable[] memory recipients_, uint256[] memory bps); /** * @dev CreatorCore - Support for Zora * * convertBidShares */ function convertBidShares( address collectionAddress, uint256 tokenId ) external view returns (address payable[] memory recipients_, uint256[] memory bps); /* @notice Called from a collection contract to set a primary royalty override @param collectionAddress - The collection address @param sender - The address of the caller @param RoyaltyReceiver[] - The royalty receivers details */ function registerCollectionRoyaltyReceivers( address collectionAddress, address sender, RoyaltiesState.RoyaltyReceiver[] memory royaltyReceivers ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; library RoyaltiesState { struct RoyaltyReceiver { address payable wallet; uint48 primarySalePercentage; uint48 secondarySalePercentage; } /** * @dev Storage layout * This pattern allow us to extend current contract using DELETGATE_CALL * without worrying about storage slot conflicts */ struct RoyaltiesRegistryState { // contractAddress => RoyaltyReceiver mapping(address => RoyaltyReceiver[]) _collectionRoyaltyReceivers; // contractAddress => editionId => RoyaltyReceiver mapping(address => mapping(uint256 => RoyaltyReceiver[])) _editionRoyaltyReceivers; // contractAddress => editionId => tokenNumber => RoyaltyReceiver mapping(address => mapping(uint256 => mapping(uint256 => RoyaltyReceiver[]))) _tokenRoyaltyReceivers; } /** * @dev Get storage data from dedicated slot. * This pattern avoids storage conflict during proxy upgrades * and give more flexibility when creating extensions */ function _getRoyaltiesState() internal pure returns (RoyaltiesRegistryState storage state) { bytes32 storageSlot = keccak256("liveart.RoyalitiesState"); assembly { state.slot := storageSlot } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; interface IRaribleV1 { /* * bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f * bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb * * => 0x0ebd4c7f ^ 0xb9c4d9fb == 0xb7799584 */ function getFeeBps(uint256 id) external view returns (uint256[] memory); function getFeeRecipients(uint256 id) external view returns (address payable[] memory); } interface IRaribleV2 { /* * bytes4(keccak256('getRaribleV2Royalties(uint256)')) == 0xcad96cca */ struct Part { address payable account; uint96 value; } function getRaribleV2Royalties(uint256 id) external view returns (Part[] memory); }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../extensions/AccessControl.sol"; import "../extensions/Winter.sol"; import "./IERC721LA.sol"; import "../extensions/Pausable.sol"; import "../extensions/IERC4906.sol"; import "../extensions/Ownable.sol"; import "../extensions/LAInitializable.sol"; import "../libraries/LANFTUtils.sol"; import "../libraries/BPS.sol"; import "../libraries/CustomErrors.sol"; import "./IERC721Events.sol"; import "./ERC721State.sol"; import "../extensions/WithOperatorRegistry.sol"; interface IStakingContract { function isTokenStaked(uint256 tokenId) external view returns (bool); } interface IPrintVoucherContract { function mintPrintVoucher( address _recipient, uint256[] calldata _tokenIds ) external; } /** * @notice LiveArt ERC721 implementation contract * Supports multiple edtioned NFTs and gas optimized batch minting */ abstract contract ERC721LACore is LAInitializable, AccessControl, WithOperatorRegistry, Winter, Pausable, Ownable, IERC721LA, IERC4906 { /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LIBRARIES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ using BitMaps for BitMaps.BitMap; using ERC721State for ERC721State.ERC721LAState; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LIBRARIES * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ using BitMaps for BitMaps.BitMap; using ERC721State for ERC721State.ERC721LAState; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * CONSTANTS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ bytes32 public constant IERC721METADATA_INTERFACE = hex"5b5e139f"; bytes32 public constant IERC721_INTERFACE = hex"80ac58cd"; bytes32 public constant IERC2981_INTERFACE = hex"2a55205a"; bytes32 public constant IERC165_INTERFACE = hex"01ffc9a7"; bytes32 public constant IERC4906_INTERFACE = hex"49064906"; // Used for separating editionId and tokenNumber from the tokenId (cf. createEdition) uint24 public constant DEFAULT_EDITION_TOKEN_MULTIPLIER = 10e5; // Used to differenciate burnt tokens in the bitmap logic (Null address being used for unminted tokens) address public constant burnAddress = address(0xDEAD); // Logic contracts addresses address public constant GOERLI_LOGIC_CONTRACT = address(0xBb7093937225983269A7003e15a7b8200f8b523d); address public constant MAINNET_LOGIC_CONTRACT = address(0xE291354a3aeB7EB49da0f1333d667F17fa33F1c5); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INITIALIZERS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * @dev Initialize function. Should be called by the factory when deploying new instances. * @param _collectionAdmin is the address of the default admin for this contract */ function initialize( string calldata _name, string calldata _symbol, address _collectionAdmin, address _royaltyRegistry ) external notInitialized { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._name = _name; state._symbol = _symbol; state._royaltyRegistry = IRoyaltiesRegistry(_royaltyRegistry); state._editionCounter = 1; state._edition_max_tokens = DEFAULT_EDITION_TOKEN_MULTIPLIER; _grantRole(COLLECTION_ADMIN_ROLE, _collectionAdmin); _setOwner(_collectionAdmin); _setWinterWallet(0xdAb1a1854214684acE522439684a145E62505233); _initOperatorRegsitry(); } /** * @dev Overload `initialize` function with `_edition_max_tokens` argument */ // function initialize( // string calldata _name, // string calldata _symbol, // address _collectionAdmin, // address _royaltyRegistry, // uint24 _edition_max_tokens // ) external notInitialized { // ERC721State.ERC721LAState storage state = ERC721State // ._getERC721LAState(); // state._name = _name; // state._symbol = _symbol; // state._royaltyRegistry = IRoyaltiesRegistry(_royaltyRegistry); // state._editionCounter = 1; // state._edition_max_tokens = _edition_max_tokens; // _grantRole(COLLECTION_ADMIN_ROLE, _collectionAdmin); // _setOwner(_collectionAdmin); // _setWinterWallet(0xdAb1a1854214684acE522439684a145E62505233); // _initOperatorRegsitry(); // } /// @dev See {IERC165-supportsInterface}. // function supportsInterface( // bytes4 interfaceId // ) external pure override returns (bool) { // return // interfaceId == IERC4906_INTERFACE || // interfaceId == IERC2981_INTERFACE || // interfaceId == IERC721_INTERFACE || // interfaceId == IERC721METADATA_INTERFACE || // interfaceId == IERC165_INTERFACE; // } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * LogicContract * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function _delegateLogic() internal virtual { address implementation = getLogicContract(); assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize()) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall( gas(), implementation, 0, calldatasize(), 0, 0 ) // Copy the returned data. returndatacopy(0, 0, returndatasize()) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } function getLogicContract() internal view returns (address) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); if (state._logicContractAddress != address(0)) { return state._logicContractAddress; } if (block.chainid == 5) { return GOERLI_LOGIC_CONTRACT; } return MAINNET_LOGIC_CONTRACT; } function setLogicContractAddress(address newAddress) external onlyAdmin { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._logicContractAddress = newAddress; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * IERC721Metadata * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function name() external view override returns (string memory) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._name; } function symbol() external view returns (string memory) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._symbol; } // function setName(string calldata _name) public onlyAdmin { // ERC721State.ERC721LAState storage state = ERC721State // ._getERC721LAState(); // state._name = _name; // } // function setSymbol(string calldata _symbol) public onlyAdmin { // ERC721State.ERC721LAState storage state = ERC721State // ._getERC721LAState(); // state._symbol = _symbol; // } function tokenURI( uint256 tokenId ) external view override returns (string memory) { if (!_exists(tokenId)) { revert CustomErrors.TokenNotFound(); } ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); (uint256 editionId, ) = parseEditionFromTokenId(tokenId); ERC721State.Edition memory edition = getEdition(editionId); if (edition.perTokenMetadata) { return string( abi.encodePacked( state._baseURIByEdition[editionId], LANFTUtils.toString(tokenId) ) ); } return state._baseURIByEdition[editionId]; } function totalSupply() external view override returns (uint256) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); uint256 _count; for (uint256 i = 1; i < state._editionCounter; i += 1) { _count += editionMintedTokens(i); } return _count; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * EDITIONS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * @notice Backward compatibility with the frontend */ function EDITION_TOKEN_MULTIPLIER() public view returns (uint24) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._edition_max_tokens; } function EDITION_MAX_SIZE() public view returns (uint24) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._edition_max_tokens - 1; } /** * @notice Creates a new Edition * Editions can be seen as collections within a collection. * The token Ids for the a given edition have the following format: * `[editionId][tokenNumber]` * eg.: The Id of the 2nd token of the 5th edition is: `5000002` * */ function createEdition( string calldata _baseURI, uint24 _maxSupply, uint24 _publicMintPriceInFinney, uint32 _publicMintStartTS, uint32 _publicMintEndTS, uint8 _maxMintPerWallet, bool _perTokenMetadata, uint8 _burnableEditionId, uint8 _amountToBurn ) public onlyAdmin returns (uint256) { _delegateLogic(); } /** * @notice updates an edition base URI */ function updateEditionBaseURI( uint256 editionId, string calldata _baseURI ) public onlyAdmin { _delegateLogic(); } /** * @notice updates an edition base URI */ function updateEditionPrintData( uint256 _editionId, address _newPrintVoucherAddress, uint24 _newPublicMintPriceWithPrintInFinney ) public onlyAdmin { _delegateLogic(); } /** * @notice updates edition parameter. Careful: This will overwrite all previously set values on that edition. */ function updateEdition( uint256 editionId, uint24 _publicMintPriceInFinney, uint32 _publicMintStartTS, uint32 _publicMintEndTS, uint8 _maxMintPerWallet, uint24 _maxSupply, bool _perTokenMetadata ) public onlyAdmin { _delegateLogic(); } /** * @notice fetch edition struct data by editionId */ function getEdition( uint256 _editionId ) public view override returns (ERC721State.Edition memory) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); if (_editionId > state._editionCounter) { revert CustomErrors.InvalidEditionId(); } return state._editions[_editionId]; } /** * @notice fetch edition struct data by editionId */ function getEditionWithURI( uint256 _editionId ) public view override returns (ERC721State.EditionWithURI memory editionWithURI) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); if (_editionId > state._editionCounter) { revert CustomErrors.InvalidEditionId(); } editionWithURI = ERC721State.EditionWithURI({ data: state._editions[_editionId], baseURI: state._baseURIByEdition[_editionId] }); } function getEditionPrintData( uint256 _editionId ) public view override returns (ERC721State.EditionWithPrintData memory editionPrintData) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); if (_editionId > state._editionCounter) { revert CustomErrors.InvalidEditionId(); } editionPrintData = ERC721State.EditionWithPrintData({ printVoucherContractAddress: state ._printDataByEdition[_editionId] .printVoucherContractAddress, publicMintPriceWithPrintInFinney: state ._printDataByEdition[_editionId] .publicMintPriceWithPrintInFinney }); } /** * @notice Returns the total number of editions */ function totalEditions() external view returns (uint256 total) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); total = state._editionCounter - 1; } /** * @notice Returns the current supply of a given edition */ function editionMintedTokens( uint256 editionId ) public view returns (uint256 supply) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); ERC721State.Edition memory edition = state._editions[editionId]; return edition.currentSupply - edition.burnedSupply; } /** * @dev Given an editionId and tokenNumber, returns tokenId in the following format: * `[editionId][tokenNumber]` where `tokenNumber` is between 1 and state._edition_max_tokens - 1 * eg.: The second token from the 5th edition would be `500002` * */ function editionedTokenId( uint256 editionId, uint256 tokenNumber ) public view returns (uint256 tokenId) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); uint256 paddedEditionID = editionId * state._edition_max_tokens; tokenId = paddedEditionID + tokenNumber; } /** * @dev Given a tokenId return editionId and tokenNumber. * eg.: 3000005 => editionId 3 and tokenNumber 5 */ function parseEditionFromTokenId( uint256 tokenId ) public view returns (uint256 editionId, uint256 tokenNumber) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); // Divide first to lose the decimal. ie. 1000001 / 1000000 = 1 editionId = tokenId / state._edition_max_tokens; tokenNumber = tokenId - (editionId * state._edition_max_tokens); } /// @dev Is public mint open for given edition function isPublicMintStarted( uint256 editionId ) public view override returns (bool) { ERC721State.Edition memory edition = getEdition(editionId); bool started = (edition.publicMintStartTS != 0 && edition.publicMintStartTS <= block.timestamp) && (edition.publicMintEndTS == 0 || edition.publicMintEndTS > block.timestamp); return started; } /** * @notice sets the staking contract address **/ function setStakingContractAddress( address stakingContractAddress ) external onlyAdmin { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._stakingContractAddress = stakingContractAddress; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * STAKING * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * @notice toggle staking on/off for an edition **/ function toggleStakingByEdition(uint256 editionId) external onlyAdmin { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._editions[editionId].stakingEnabled = !state ._editions[editionId] .stakingEnabled; } function getStakingContractAddress() external view returns (address) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._stakingContractAddress; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * STAKING * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ modifier whenPublicMintOpened(uint256 editionId) { if (!isPublicMintStarted(editionId)) { revert CustomErrors.MintClosed(); } _; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * MINTABLE * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * @dev Internal batch minting function */ function _safeMint( uint256 _editionId, uint24 _quantity, address _recipient ) internal virtual returns (uint256 firstTokenId) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); ERC721State.Edition storage edition = state._editions[_editionId]; uint256 tokenNumber = edition.currentSupply + 1; if (_editionId > state._editionCounter) { revert CustomErrors.InvalidEditionId(); } if (_quantity == 0 || _recipient == address(0)) { revert CustomErrors.InvalidMintData(); } if (tokenNumber > edition.maxSupply) { revert CustomErrors.MaxSupplyError(); } firstTokenId = editionedTokenId(_editionId, tokenNumber); if (edition.currentSupply + _quantity > edition.maxSupply) { revert CustomErrors.MaxSupplyError(); } edition.currentSupply += _quantity; state._owners[firstTokenId] = _recipient; state._batchHead.set(firstTokenId); state._balances[_recipient] += _quantity; // Emit events for ( uint256 tokenId = firstTokenId; tokenId < firstTokenId + _quantity; tokenId++ ) { emit Transfer(address(0), _recipient, tokenId); LANFTUtils._checkOnERC721Received( address(0), _recipient, tokenId, "" ); } } function mintEditionTokens( uint256 _editionId, uint24 _quantity, address _recipient ) public payable whenPublicMintOpened(_editionId) whenNotPaused { ERC721State.Edition memory edition = getEdition(_editionId); _validatePublicMintParams( _editionId, _quantity, edition.maxMintPerWallet ); _validateMintPrice(edition.publicMintPriceInFinney, _quantity); uint256 firstTokenId = _safeMint(_editionId, _quantity, _recipient); _sendRoyaltiesAfterMint(firstTokenId); } function mintEditionTokensWithPrints( uint256 _editionId, uint24 _quantity, address _recipient ) public payable whenPublicMintOpened(_editionId) whenNotPaused { ERC721State.Edition memory edition = getEdition(_editionId); ERC721State.EditionWithPrintData memory printData = getEditionPrintData( _editionId ); _validatePublicMintParams( _editionId, _quantity, edition.maxMintPerWallet ); _validateEditionPrintData(printData); _validateMintPrice( printData.publicMintPriceWithPrintInFinney, _quantity ); uint256 firstTokenId = _safeMint(_editionId, _quantity, _recipient); _sendRoyaltiesAfterMint(firstTokenId); _mintPrintVouchers(_editionId, _quantity, firstTokenId); } function adminMint( uint256 _editionId, uint24 _quantity, address _recipient ) public onlyAdmin { _safeMint(_editionId, _quantity, _recipient); } function getMintedCount( uint256 _editionId, address _recipient ) public view returns (uint256) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); uint256 mintedCountKey = uint256( keccak256(abi.encodePacked(_editionId, _recipient)) ); return state._mintedPerWallet[mintedCountKey]; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * PAUSABLE * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function pauseContract() public onlyAdmin { _pause(); } function unpauseContract() public onlyAdmin { _unpause(); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ERC721 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /// @dev See {IERC721-approve}. function approve( address to, uint256 tokenId ) external override onlyAllowedOperatorApproval(to) { address owner = ownerOf(tokenId); if ( msg.sender == to || (msg.sender != owner && !isApprovedForAll(owner, msg.sender)) ) { revert CustomErrors.NotAllowed(); } _approve(to, tokenId); } /// @dev See {IERC721-transferFrom}. function transferFrom( address from, address to, uint256 tokenId ) external override onlyAllowedOperator(from) { if (!_isApprovedOrOwner(msg.sender, tokenId)) { revert CustomErrors.TransferError(); } _transfer(from, to, tokenId); } /// @dev See {IERC721-ownerOf}. function ownerOf(uint256 tokenId) public view override returns (address) { (address owner, ) = _ownerAndBatchHeadOf(tokenId); return owner; } /// @dev Returns the number of tokens in ``owner``'s account. function balanceOf( address owner ) external view returns (uint256 tokenBalance) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); tokenBalance = state._balances[owner]; } /// @dev See {IERC721-getApproved}. function getApproved( uint256 tokenId ) public view override returns (address) { if (!_exists(tokenId)) { revert CustomErrors.TokenNotFound(); } ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); if (!_isTransferAllowed(tokenId)) { revert CustomErrors.TokenStaked(); } return state._tokenApprovals[tokenId]; } /// @dev See {IERC721-isApprovedForAll}. function isApprovedForAll( address owner, address operator ) public view override returns (bool) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._operatorApprovals[owner][operator]; } /// @dev See {IERC721-setApprovalForAll}. function setApprovalForAll( address operator, bool approved ) external override onlyAllowedOperatorApproval(operator) { if (operator == msg.sender) { revert CustomErrors.NotAllowed(); } ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._operatorApprovals[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } /// @dev See {IERC721-safeTransferFrom}. function safeTransferFrom( address from, address to, uint256 tokenId ) external override onlyAllowedOperator(from) { safeTransferFrom(from, to, tokenId, ""); } /// @dev See {IERC721-safeTransferFrom}. function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public override onlyAllowedOperator(from) { if (!_isApprovedOrOwner(msg.sender, tokenId)) { revert CustomErrors.NotAllowed(); } _safeTransfer(from, to, tokenId, _data); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * INTERNAL / PUBLIC HELPERS * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /// @dev Returns whether `tokenId` exists. function _exists(uint256 tokenId) internal view virtual returns (bool) { (uint256 editionId, uint256 tokenNumber) = parseEditionFromTokenId( tokenId ); if (isBurned(tokenId)) { return false; } ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); ERC721State.Edition memory edition = state._editions[editionId]; return tokenNumber <= edition.currentSupply; } /** * @dev Returns the index of the batch for a given token. * If the token was not bought in a batch tokenId == tokenIdBatchHead */ function _getBatchHead( uint256 tokenId ) internal view returns (uint256 tokenIdBatchHead) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); (uint256 editionId, ) = parseEditionFromTokenId(tokenId); tokenIdBatchHead = state._batchHead.scanForward( tokenId, editionId * state._edition_max_tokens ); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._tokenApprovals[tokenId] = to; emit Approval(ownerOf(tokenId), to, tokenId); } /** * @dev Returns the index of the batch for a given token. * and the batch owner address */ function _ownerAndBatchHeadOf( uint256 tokenId ) internal view returns (address owner, uint256 tokenIdBatchHead) { if (!_exists(tokenId)) { revert CustomErrors.TokenNotFound(); } ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); tokenIdBatchHead = _getBatchHead(tokenId); owner = state._owners[tokenIdBatchHead]; } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner( address spender, uint256 tokenId ) internal view returns (bool) { if (!_exists(tokenId)) { revert CustomErrors.TokenNotFound(); } address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Transfers `tokenId` from `from` to `to`. * Internal function intened to split the logic for different transfer use cases * Emits a {Transfer} event. */ function _transferCore(address from, address to, uint256 tokenId) internal { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); (, uint256 tokenIdBatchHead) = _ownerAndBatchHeadOf(tokenId); address owner = ownerOf(tokenId); if (owner != from) { revert CustomErrors.TransferError(); } // We check if the token after the one being transfer // belong to the batch, if it does, we have to update it's owner // while being careful to not overflow the edition maxSupply uint256 nextTokenId = tokenId + 1; (, uint256 nextTokenNumber) = parseEditionFromTokenId(nextTokenId); (uint256 currentEditionId, ) = parseEditionFromTokenId(tokenId); ERC721State.Edition memory edition = state._editions[currentEditionId]; if ( nextTokenNumber <= edition.maxSupply && !state._batchHead.get(nextTokenId) ) { state._owners[nextTokenId] = from; state._batchHead.set(nextTokenId); } // Finaly we update the owners and balances state._owners[tokenId] = to; if (tokenId != tokenIdBatchHead) { state._batchHead.set(tokenId); } state._balances[to] += 1; state._balances[from] -= 1; } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal { _beforeTokenTransfer(from, to, tokenId); // Remove approval _approve(address(0), tokenId); emit Transfer(from, to, tokenId); _transferCore(from, to, tokenId); } function _safeTransfer( address from, address to, uint256 tokenId, bytes memory _data ) internal virtual { _transfer(from, to, tokenId); LANFTUtils._checkOnERC721Received(from, to, tokenId, _data); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual { if (!_isTransferAllowed(tokenId)) { revert CustomErrors.TokenStaked(); } } /** * Check if the token is staked */ function _isTransferAllowed(uint256 tokenId) internal view returns (bool) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); (uint256 currentEditionId, ) = parseEditionFromTokenId(tokenId); ERC721State.Edition memory edition = state._editions[currentEditionId]; // If the token is staked, we don't allow transfer if (edition.stakingEnabled) { bool tokenIsStaked = IStakingContract(state._stakingContractAddress) .isTokenStaked(tokenId); if (tokenIsStaked) { return false; } } return true; } function _mintPrintVouchers( uint256 _editionId, uint24 _quantity, uint256 _firstTokenId ) internal { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); address printVoucherContractAddress = state ._printDataByEdition[_editionId] .printVoucherContractAddress; // Mint print vouchers uint256[] memory tokenArray = new uint256[](_quantity); for (uint256 i = 0; i < _quantity; i++) { tokenArray[i] = _firstTokenId + i; } IPrintVoucherContract(printVoucherContractAddress).mintPrintVoucher( tx.origin, tokenArray ); } function _validatePublicMintParams( uint256 _editionId, uint24 _quantity, uint8 _maxMintPerWallet ) internal { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); // Check max mint per wallet restrictions (if maxMintPerWallet is 0, no restriction apply) if (_maxMintPerWallet != 0 && !_isWinterWallet()) { uint256 mintedCountKey = uint256( keccak256(abi.encodePacked(_editionId, msg.sender)) ); if ( state._mintedPerWallet[mintedCountKey] + _quantity > _maxMintPerWallet ) { revert CustomErrors.MaximumMintAmountReached(); } state._mintedPerWallet[mintedCountKey] += _quantity; } } function _validateEditionPrintData( ERC721State.EditionWithPrintData memory printData ) internal pure { if ( printData.printVoucherContractAddress == address(0) || printData.publicMintPriceWithPrintInFinney == 0 ) { revert CustomErrors.InvalidPrintData(); } } function _validateMintPrice( uint256 _mintPriceInFinney, uint24 _quantity ) internal view { uint256 mintPriceInWei = uint256(_mintPriceInFinney) * 10e14; if (mintPriceInWei * _quantity > msg.value) { revert CustomErrors.InsufficientFunds(); } } function _sendRoyaltiesAfterMint(uint256 _firstTokenId) internal { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); // Send primary royalties ( address payable[] memory wallets, uint256[] memory primarySalePercentages ) = state._royaltyRegistry.primaryRoyaltyInfo( address(this), _firstTokenId ); uint256 nReceivers = wallets.length; for (uint256 i = 0; i < nReceivers; i++) { uint256 royalties = BPS._calculatePercentage( msg.value, primarySalePercentages[i] ); (bool sent, ) = wallets[i].call{value: royalties}(""); if (!sent) { revert CustomErrors.FundTransferError(); } } } /** * Check if the token is staked */ // function _areAllNFTsStaked(address from) internal view returns(bool) { // ERC721State.ERC721LAState storage state = ERC721State // ._getERC721LAState(); // (uint256 currentEditionId, ) = parseEditionFromTokenId(tokenId); // ERC721State.Edition memory edition = state._editions[currentEditionId]; // // If the token is staked, we don't allow transfer // if (edition.stakingEnabled) { // bool tokenIsStaked = IStakingContract(state._stakingContractAddress) // .isTokenStaked(tokenId); // if (tokenIsStaked) { // return false; // } // } // return true; // } function isBurned(uint256 tokenId) public view returns (bool) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); address owner = state._owners[tokenId]; return owner == burnAddress; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ETHER * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function balance() public view returns (uint256) { return address(this).balance; } function withdrawAmount( address payable recipient, uint256 amount ) external onlyAdmin { (bool succeed, ) = recipient.call{value: amount}(""); if (!succeed) { revert CustomErrors.FundTransferError(); } } function withdrawAll(address payable recipient) external onlyAdmin { (bool succeed, ) = recipient.call{value: balance()}(""); if (!succeed) { revert CustomErrors.FundTransferError(); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * X-CARD * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function setXCardContractAddress( address xCardContractAddress ) public override onlyAdmin { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); state._xCardContractAddress = xCardContractAddress; } function getXCardContractAddress() public view override returns (address) { ERC721State.ERC721LAState storage state = ERC721State ._getERC721LAState(); return state._xCardContractAddress; } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../libraries/BitMaps/BitMaps.sol"; import "../platform/royalties/IRoyaltiesRegistry.sol"; library ERC721State { using BitMaps for BitMaps.BitMap; struct Edition { // Max. number of token mintable per edition uint24 maxSupply; // Currently minted token coutner uint24 currentSupply; // Burned token counter uint24 burnedSupply; // Public mint price uint24 publicMintPriceInFinney; // Public mint start time in seconds uint32 publicMintStartTS; // Public mint ending time in seconds uint32 publicMintEndTS; // Max mint per wallet. If 0, no limit uint8 maxMintPerWallet; // If perTokenMetadata == false, all tokens in this edition will have the same metadata bool perTokenMetadata; // An edition Id associated with this collection that is approved to be burned in order to mint on the current edition. uint24 burnableEditionId; // Amount to burn uint24 amountToBurn; // determines if this edition supports staking bool stakingEnabled; } struct EditionWithURI { Edition data; string baseURI; } /** * @dev Storage layout * This pattern allow us to extend current contract using DELETGATE_CALL * without worrying about storage slot conflicts */ struct ERC721LAState { // The number of edition created, indexed from 1 uint64 _editionCounter; // Max token by edition. Defines the number of 0 in token Id (see editions) uint24 _edition_max_tokens; // Contract Name string _name; // Ticker string _symbol; // Edtion by editionId mapping(uint256 => Edition) _editions; // Owner by tokenId mapping(uint256 => address) _owners; // Token Id to operator address mapping(uint256 => address) _tokenApprovals; // Owned token count by address mapping(address => uint256) _balances; // Allower to allowee mapping(address => mapping(address => bool)) _operatorApprovals; // Tracking of batch heads BitMaps.BitMap _batchHead; // LiveArt global royalty registry address IRoyaltiesRegistry _royaltyRegistry; // Amount of ETH withdrawn by edition mapping(uint256 => uint256) _withdrawnBalancesByEdition; // EditionID => Base URI mapping(uint256 => string) _baseURIByEdition; // Minted counter per wallet/edition. hash(address, editionId) => counter mapping(uint256 => uint256) _mintedPerWallet; // xCardContract Address address _xCardContractAddress; // Staking contract address address _stakingContractAddress; // Logic contract address address _logicContractAddress; // EditionPrintData by editionId mapping(uint256 => EditionWithPrintData) _printDataByEdition; } struct EditionWithPrintData { address printVoucherContractAddress; uint24 publicMintPriceWithPrintInFinney; } /** * @dev Get storage data from dedicated slot. * This pattern avoids storage conflict during proxy upgrades * and give more flexibility when creating extensions */ function _getERC721LAState() internal pure returns (ERC721LAState storage state) { bytes32 storageSlot = keccak256("liveart.ERC721LA"); assembly { state.slot := storageSlot } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.4; import "../libraries/BitMaps/BitMaps.sol"; import "../platform/royalties/IRoyaltiesRegistry.sol"; interface IERC721Events { event EditionCreated( address indexed contractAddress, uint256 editionId, uint24 maxSupply, string baseURI, uint24 contractMintPrice, bool perTokenMetadata ); event EditionUpdated( address indexed contractAddress, uint256 editionId, uint256 maxSupply, string baseURI ); /** * @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 ); }
// SPDX-License-Identifier: UNLICENSED import "../libraries/BitMaps/BitMaps.sol"; import "../platform/royalties/IRoyaltiesRegistry.sol"; import "./IERC721Events.sol"; import "./ERC721State.sol"; pragma solidity ^0.8.4; /** * @dev Interface of an ERC721LA compliant contract. */ abstract contract IERC721LA is IERC721Events { using BitMaps for BitMaps.BitMap; // ============================== // 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 virtual returns (bool); // ============================== // IERC721 // ============================== /** * @dev Returns the total amount of tokens stored by the contract. * * Burned tokens are calculated here, use `_totalMinted()` if you want to count just minted tokens. */ function totalSupply() external view virtual returns (uint256); /** * @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 virtual 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 virtual; /** * @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 be 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 virtual; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * 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 virtual; /** * @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 virtual; /** * @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 virtual; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved( uint256 tokenId ) external view virtual 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 virtual returns (bool); // ============================== // IERC721Metadata // ============================== /** * @dev Returns the token collection name. */ function name() external view virtual returns (string memory); /** * @dev Returns the token collection symbol. */ // function symbol() external view virtual returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI( uint256 tokenId ) external view virtual returns (string memory); // ============================== // Editions // ============================== /** * @dev fetch edition struct data by editionId */ function getEdition( uint256 _editionId ) external view virtual returns (ERC721State.Edition memory); /** * @dev fetch edition struct data by editionId */ function getEditionWithURI( uint256 _editionId ) external view virtual returns (ERC721State.EditionWithURI memory); /** * @dev fetch editionPrintData struct data by editionId */ function getEditionPrintData( uint256 _editionId ) external view virtual returns (ERC721State.EditionWithPrintData memory editionPrintData); // ============================== // Helpers // ============================== function setXCardContractAddress( address xCardContractAddress ) external virtual; function getXCardContractAddress() external view virtual returns (address); function isPublicMintStarted( uint256 editionId ) external view virtual returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; interface IOperatorFilterRegistry { /** * @notice Returns true if operator is not filtered for a given token, either by address or codeHash. Also returns * true if supplied registrant address is not registered. */ function isOperatorAllowed(address registrant, address operator) external view returns (bool); /** * @notice Registers an address with the registry. May be called by address itself or by EIP-173 owner. */ function register(address registrant) external; /** * @notice Registers an address with the registry and "subscribes" to another address's filtered operators and codeHashes. */ function registerAndSubscribe(address registrant, address subscription) external; /** * @notice Registers an address with the registry and copies the filtered operators and codeHashes from another * address without subscribing. */ function registerAndCopyEntries(address registrant, address registrantToCopy) external; /** * @notice Unregisters an address with the registry and removes its subscription. May be called by address itself or by EIP-173 owner. * Note that this does not remove any filtered addresses or codeHashes. * Also note that any subscriptions to this registrant will still be active and follow the existing filtered addresses and codehashes. */ function unregister(address addr) external; /** * @notice Update an operator address for a registered address - when filtered is true, the operator is filtered. */ function updateOperator(address registrant, address operator, bool filtered) external; /** * @notice Update multiple operators for a registered address - when filtered is true, the operators will be filtered. Reverts on duplicates. */ function updateOperators(address registrant, address[] calldata operators, bool filtered) external; /** * @notice Update a codeHash for a registered address - when filtered is true, the codeHash is filtered. */ function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; /** * @notice Update multiple codeHashes for a registered address - when filtered is true, the codeHashes will be filtered. Reverts on duplicates. */ function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; /** * @notice Subscribe an address to another registrant's filtered operators and codeHashes. Will remove previous * subscription if present. * Note that accounts with subscriptions may go on to subscribe to other accounts - in this case, * subscriptions will not be forwarded. Instead the former subscription's existing entries will still be * used. */ function subscribe(address registrant, address registrantToSubscribe) external; /** * @notice Unsubscribe an address from its current subscribed registrant, and optionally copy its filtered operators and codeHashes. */ function unsubscribe(address registrant, bool copyExistingEntries) external; /** * @notice Get the subscription address of a given registrant, if any. */ function subscriptionOf(address addr) external returns (address registrant); /** * @notice Get the set of addresses subscribed to a given registrant. * Note that order is not guaranteed as updates are made. */ function subscribers(address registrant) external returns (address[] memory); /** * @notice Get the subscriber at a given index in the set of addresses subscribed to a given registrant. * Note that order is not guaranteed as updates are made. */ function subscriberAt(address registrant, uint256 index) external returns (address); /** * @notice Copy filtered operators and codeHashes from a different registrantToCopy to addr. */ function copyEntriesOf(address registrant, address registrantToCopy) external; /** * @notice Returns true if operator is filtered by a given address or its subscription. */ function isOperatorFiltered(address registrant, address operator) external returns (bool); /** * @notice Returns true if the hash of an address's code is filtered by a given address or its subscription. */ function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); /** * @notice Returns true if a codeHash is filtered by a given address or its subscription. */ function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); /** * @notice Returns a list of filtered operators for a given address or its subscription. */ function filteredOperators(address addr) external returns (address[] memory); /** * @notice Returns the set of filtered codeHashes for a given address or its subscription. * Note that order is not guaranteed as updates are made. */ function filteredCodeHashes(address addr) external returns (bytes32[] memory); /** * @notice Returns the filtered operator at the given index of the set of filtered operators for a given address or * its subscription. * Note that order is not guaranteed as updates are made. */ function filteredOperatorAt(address registrant, uint256 index) external returns (address); /** * @notice Returns the filtered codeHash at the given index of the list of filtered codeHashes for a given address or * its subscription. * Note that order is not guaranteed as updates are made. */ function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); /** * @notice Returns true if an address has registered */ function isRegistered(address addr) external returns (bool); /** * @dev Convenience method to compute the code hash of an arbitrary contract */ function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; address constant CANONICAL_OPERATOR_FILTER_REGISTRY_ADDRESS = 0x000000000000AAeB6D7670E522A718067333cd4E; address constant CANONICAL_CORI_SUBSCRIPTION = 0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6;
{ "optimizer": { "enabled": true, "runs": 100 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AccessControlNotAllowed","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BitMapHeadNotFound","type":"error"},{"inputs":[],"name":"BurnRedeemNotAvailable","type":"error"},{"inputs":[],"name":"CallerIsNotOwner","type":"error"},{"inputs":[],"name":"FundTransferError","type":"error"},{"inputs":[],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"InvalidEditionId","type":"error"},{"inputs":[],"name":"InvalidMintData","type":"error"},{"inputs":[],"name":"InvalidMintDuration","type":"error"},{"inputs":[],"name":"InvalidPrintData","type":"error"},{"inputs":[],"name":"MaxSupplyError","type":"error"},{"inputs":[],"name":"MaximumMintAmountReached","type":"error"},{"inputs":[],"name":"MintClosed","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NotAllowed","type":"error"},{"inputs":[],"name":"NotERC721Receiver","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[],"name":"NotWhitelisted","type":"error"},{"inputs":[],"name":"TokenNotFound","type":"error"},{"inputs":[],"name":"TokenStaked","type":"error"},{"inputs":[],"name":"TooManyAddresses","type":"error"},{"inputs":[],"name":"TransferError","type":"error"},{"inputs":[],"name":"WhiteListAlreadyExists","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","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":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"editionId","type":"uint256"},{"indexed":false,"internalType":"uint24","name":"maxSupply","type":"uint24"},{"indexed":false,"internalType":"string","name":"baseURI","type":"string"},{"indexed":false,"internalType":"uint24","name":"contractMintPrice","type":"uint24"},{"indexed":false,"internalType":"bool","name":"perTokenMetadata","type":"bool"}],"name":"EditionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"editionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxSupply","type":"uint256"},{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"EditionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"AIRDROP_MAX_BATCH_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COLLECTION_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_EDITION_TOKEN_MULTIPLIER","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EDITION_MAX_SIZE","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EDITION_TOKEN_MULTIPLIER","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOERLI_LOGIC_CONTRACT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IERC165_INTERFACE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IERC2981_INTERFACE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IERC4906_INTERFACE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IERC721METADATA_INTERFACE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IERC721_INTERFACE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAINNET_LOGIC_CONTRACT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"addWinterWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint24","name":"_quantity","type":"uint24"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"adminMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint24","name":"quantityPerAddress","type":"uint24"}],"name":"airdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"balance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"tokenBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"burnMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint24","name":"_quantity","type":"uint24"},{"internalType":"uint256[]","name":"tokenIdsToBurn","type":"uint256[]"}],"name":"burnRedeemEditionTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"},{"internalType":"uint24","name":"_maxSupply","type":"uint24"},{"internalType":"uint24","name":"_publicMintPriceInFinney","type":"uint24"},{"internalType":"uint32","name":"_publicMintStartTS","type":"uint32"},{"internalType":"uint32","name":"_publicMintEndTS","type":"uint32"},{"internalType":"uint8","name":"_maxMintPerWallet","type":"uint8"},{"internalType":"bool","name":"_perTokenMetadata","type":"bool"},{"internalType":"uint8","name":"_burnableEditionId","type":"uint8"},{"internalType":"uint8","name":"_amountToBurn","type":"uint8"}],"name":"createEdition","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"deleteWinterWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"}],"name":"editionMintedTokens","outputs":[{"internalType":"uint256","name":"supply","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint256","name":"tokenNumber","type":"uint256"}],"name":"editionedTokenId","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"}],"name":"getEdition","outputs":[{"components":[{"internalType":"uint24","name":"maxSupply","type":"uint24"},{"internalType":"uint24","name":"currentSupply","type":"uint24"},{"internalType":"uint24","name":"burnedSupply","type":"uint24"},{"internalType":"uint24","name":"publicMintPriceInFinney","type":"uint24"},{"internalType":"uint32","name":"publicMintStartTS","type":"uint32"},{"internalType":"uint32","name":"publicMintEndTS","type":"uint32"},{"internalType":"uint8","name":"maxMintPerWallet","type":"uint8"},{"internalType":"bool","name":"perTokenMetadata","type":"bool"},{"internalType":"uint24","name":"burnableEditionId","type":"uint24"},{"internalType":"uint24","name":"amountToBurn","type":"uint24"},{"internalType":"bool","name":"stakingEnabled","type":"bool"}],"internalType":"struct ERC721State.Edition","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"}],"name":"getEditionPrintData","outputs":[{"components":[{"internalType":"address","name":"printVoucherContractAddress","type":"address"},{"internalType":"uint24","name":"publicMintPriceWithPrintInFinney","type":"uint24"}],"internalType":"struct ERC721State.EditionWithPrintData","name":"editionPrintData","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"}],"name":"getEditionWithURI","outputs":[{"components":[{"components":[{"internalType":"uint24","name":"maxSupply","type":"uint24"},{"internalType":"uint24","name":"currentSupply","type":"uint24"},{"internalType":"uint24","name":"burnedSupply","type":"uint24"},{"internalType":"uint24","name":"publicMintPriceInFinney","type":"uint24"},{"internalType":"uint32","name":"publicMintStartTS","type":"uint32"},{"internalType":"uint32","name":"publicMintEndTS","type":"uint32"},{"internalType":"uint8","name":"maxMintPerWallet","type":"uint8"},{"internalType":"bool","name":"perTokenMetadata","type":"bool"},{"internalType":"uint24","name":"burnableEditionId","type":"uint24"},{"internalType":"uint24","name":"amountToBurn","type":"uint24"},{"internalType":"bool","name":"stakingEnabled","type":"bool"}],"internalType":"struct ERC721State.Edition","name":"data","type":"tuple"},{"internalType":"string","name":"baseURI","type":"string"}],"internalType":"struct ERC721State.EditionWithURI","name":"editionWithURI","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"getMintedCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakingContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint8","name":"amount","type":"uint8"},{"internalType":"uint24","name":"mintPriceInFinney","type":"uint24"},{"internalType":"uint24","name":"mintPriceWithPrintInFinney","type":"uint24"}],"name":"getWLConfig","outputs":[{"components":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint8","name":"amount","type":"uint8"},{"internalType":"uint24","name":"mintPriceInFinney","type":"uint24"},{"internalType":"uint32","name":"mintStartTS","type":"uint32"},{"internalType":"uint32","name":"mintEndTS","type":"uint32"},{"internalType":"uint24","name":"mintPriceWithPrintInFinney","type":"uint24"}],"internalType":"struct WhitelistableState.WhitelistConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getXCardContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initOperatorRegsitry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_collectionAdmin","type":"address"},{"internalType":"address","name":"_royaltyRegistry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"theAddress","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isBurned","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"}],"name":"isPublicMintStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint24","name":"_quantity","type":"uint24"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"mintEditionTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint24","name":"_quantity","type":"uint24"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"mintEditionTokensWithPrints","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"parseEditionFromTokenId","outputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint256","name":"tokenNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"primaryRoyaltyInfo","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address payable","name":"wallet","type":"address"},{"internalType":"uint48","name":"primarySalePercentage","type":"uint48"},{"internalType":"uint48","name":"secondarySalePercentage","type":"uint48"}],"internalType":"struct RoyaltiesState.RoyaltyReceiver[]","name":"royaltyReceivers","type":"tuple[]"}],"name":"registerCollectionRoyaltyReceivers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyRegistryAddress","outputs":[{"internalType":"contract IRoyaltiesRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","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":"address","name":"newAddress","type":"address"}],"name":"setLogicContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_royaltyRegistry","type":"address"}],"name":"setRoyaltyRegistryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stakingContractAddress","type":"address"}],"name":"setStakingContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint8","name":"amount","type":"uint8"},{"internalType":"uint24","name":"mintPriceInFinney","type":"uint24"},{"internalType":"uint32","name":"mintStartTS","type":"uint32"},{"internalType":"uint32","name":"mintEndTS","type":"uint32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint24","name":"mintPriceWithPrintInFinney","type":"uint24"}],"name":"setWLConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"xCardContractAddress","type":"address"}],"name":"setXCardContractAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"}],"name":"toggleStakingByEdition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEditions","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"uint24","name":"_publicMintPriceInFinney","type":"uint24"},{"internalType":"uint32","name":"_publicMintStartTS","type":"uint32"},{"internalType":"uint32","name":"_publicMintEndTS","type":"uint32"},{"internalType":"uint8","name":"_maxMintPerWallet","type":"uint8"},{"internalType":"uint24","name":"_maxSupply","type":"uint24"},{"internalType":"bool","name":"_perTokenMetadata","type":"bool"}],"name":"updateEdition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"editionId","type":"uint256"},{"internalType":"string","name":"_baseURI","type":"string"}],"name":"updateEditionBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"address","name":"_newPrintVoucherAddress","type":"address"},{"internalType":"uint24","name":"_newPublicMintPriceWithPrintInFinney","type":"uint24"}],"name":"updateEditionPrintData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRegistry","type":"address"}],"name":"updateOperatorFilterRegistryAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint8","name":"_amount","type":"uint8"},{"internalType":"uint24","name":"mintPriceInFinney","type":"uint24"},{"internalType":"uint8","name":"newAmount","type":"uint8"},{"internalType":"uint24","name":"newMintPriceInFinney","type":"uint24"},{"internalType":"uint32","name":"newMintStartTS","type":"uint32"},{"internalType":"uint32","name":"newMintEndTS","type":"uint32"},{"internalType":"bytes32","name":"newMerkleRoot","type":"bytes32"},{"internalType":"uint24","name":"mintPriceWithPrintInFinney","type":"uint24"},{"internalType":"uint24","name":"newMintPriceWithPrintInFinney","type":"uint24"}],"name":"updateWLConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint8","name":"_maxAmount","type":"uint8"},{"internalType":"uint24","name":"_mintPriceInFinney","type":"uint24"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint24","name":"_quantity","type":"uint24"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint24","name":"_xCardTokenId","type":"uint24"},{"internalType":"uint24","name":"_mintPriceWithPrintInFinney","type":"uint24"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_editionId","type":"uint256"},{"internalType":"uint8","name":"_maxAmount","type":"uint8"},{"internalType":"uint24","name":"_mintPriceInFinney","type":"uint24"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint24","name":"_quantity","type":"uint24"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint24","name":"_xCardTokenId","type":"uint24"},{"internalType":"uint24","name":"_mintPriceWithPrintInFinney","type":"uint24"}],"name":"whitelistMintWithPrint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawAmount","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50615d1280620000216000396000f3fe60806040526004361061047e5760003560e01c806370d5ae0511610255578063ae005af911610144578063db44fe07116100c1578063eb44774011610085578063eb44774014610e16578063f2fde38b14610e2b578063f343958f14610e4b578063f45e3ebd14610e60578063fa09e63014610e95578063fc45635314610eb557600080fd5b8063db44fe0714610d18578063dc47a41014610d38578063e18827cd14610dbf578063e720a4b014610ddf578063e985e9c514610df657600080fd5b8063be5dea8a11610108578063be5dea8a14610c78578063c6879ff914610c98578063c87b56dd14610cb8578063d49232a114610cd8578063d547741f14610cf857600080fd5b8063ae005af914610bf0578063b33712c514610c10578063b69ef8a814610c25578063b88d4fde14610c38578063b8d1e53214610c5857600080fd5b8063910eec1f116101d2578063999873f711610196578063999873f714610b55578063a22cb46514610b70578063a34931c114610b90578063a642c03214610ba3578063a9359de814610bd057600080fd5b8063910eec1f14610aa757806391d1485414610af0578063933a261114610b10578063946a3cbb14610b2557806395d89b4114610b4057600080fd5b80637f12460f116102195780637f12460f146109fb57806380cd807c14610a295780638da5cb5b14610a525780638f15b41414610a675780638fc614ec14610a8757600080fd5b806370d5ae0514610962578063736fe5651461097857806373d31507146109985780637b56fc59146109b85780637cb796eb146109e057600080fd5b80633596b4ac1161037157806351d329dc116102ee57806363a5c0eb116102b257806363a5c0eb146108cd57806365308579146108ed5780636ab49a5b1461090d5780636afe57951461092d57806370a082311461094257600080fd5b806351d329dc1461084e57806357c49277146108635780635b353be2146108835780635c975abb146108985780636352211e146108ad57600080fd5b806342966c681161033557806342966c68146107c6578063434e3603146107e6578063439766ce146108065780634cb30db11461081b5780634d213ff11461082e57600080fd5b80633596b4ac1461072b57806336568abe146107535780633cbb1bb2146107735780633ebd45861461079357806342842e0e146107a657600080fd5b806323b872dd116103ff5780632a55205a116103c35780632a55205a1461066e5780632f2ff15d1461069c578063322ff140146106bc5780633474bd1e146106e957806335742d741461070957600080fd5b806323b872dd146105d057806324d7806c146105f057806325acc72e1461062057806328205b2f14610640578063287ea4341461065b57600080fd5b80630b213c07116104465780630b213c071461053257806318160ddd146105525780631a9968a9146105755780631c1f8aa3146105955780631e8f5530146105b557600080fd5b8063033da70b1461048357806306fdde03146104a5578063081812fc146104d0578063095ea7b3146104fd5780630a62f2141461051d575b600080fd5b34801561048f57600080fd5b506104a361049e366004614930565b610ed0565b005b3480156104b157600080fd5b506104ba610f16565b6040516104c791906149a5565b60405180910390f35b3480156104dc57600080fd5b506104f06104eb3660046149b8565b610fb7565b6040516104c791906149d1565b34801561050957600080fd5b506104a36105183660046149e5565b61102e565b34801561052957600080fd5b506104f06110a5565b34801561053e57600080fd5b506104a361054d366004614930565b6110c3565b34801561055e57600080fd5b506105676110e6565b6040519081526020016104c7565b34801561058157600080fd5b506104a3610590366004614a29565b611138565b3480156105a157600080fd5b506104a36105b0366004614930565b61115c565b3480156105c157600080fd5b506105676380ac58cd60e01b81565b3480156105dc57600080fd5b506104a36105eb366004614a67565b6111a2565b3480156105fc57600080fd5b5061061061060b366004614930565b6111ee565b60405190151581526020016104c7565b34801561062c57600080fd5b5061056761063b366004614aa8565b61120e565b34801561064c57600080fd5b50610567632483248360e11b81565b6104a3610669366004614b1f565b61124c565b34801561067a57600080fd5b5061068e610689366004614aa8565b61128e565b6040516104c7929190614bd1565b3480156106a857600080fd5b506104a36106b7366004614bea565b611324565b3480156106c857600080fd5b506106dc6106d73660046149b8565b611349565b6040516104c79190614cfa565b3480156106f557600080fd5b506104a3610704366004614930565b6114f6565b34801561071557600080fd5b50610567600080516020615b9d83398151915281565b34801561073757600080fd5b506104f073e291354a3aeb7eb49da0f1333d667f17fa33f1c581565b34801561075f57600080fd5b506104a361076e366004614bea565b61153c565b34801561077f57600080fd5b5061056761078e366004614d8c565b61156e565b6104a36107a1366004614e57565b61159d565b3480156107b257600080fd5b506104a36107c1366004614a67565b61163d565b3480156107d257600080fd5b506104a36107e13660046149b8565b611672565b3480156107f257600080fd5b506104a3610801366004614e97565b611745565b34801561081257600080fd5b506104a36118ec565b6104a3610829366004614e57565b61190d565b34801561083a57600080fd5b506104a3610849366004614f0f565b61198b565b34801561085a57600080fd5b50610567611a1a565b34801561086f57600080fd5b5061056761087e366004614bea565b611a4e565b34801561088f57600080fd5b50610567606481565b3480156108a457600080fd5b50610610611aa2565b3480156108b957600080fd5b506104f06108c83660046149b8565b611ab7565b3480156108d957600080fd5b506104a36108e8366004614930565b611acb565b3480156108f957600080fd5b506106106109083660046149b8565b611b11565b34801561091957600080fd5b506104a3610928366004614f6c565b611b75565b34801561093957600080fd5b506104f0611bb9565b34801561094e57600080fd5b5061056761095d366004614930565b611bd7565b34801561096e57600080fd5b506104f061dead81565b34801561098457600080fd5b506104a36109933660046149e5565b611c04565b3480156109a457600080fd5b506104a36109b3366004614fad565b611c8f565b3480156109c457600080fd5b506104f073bb7093937225983269a7003e15a7b8200f8b523d81565b3480156109ec57600080fd5b506105676301ffc9a760e01b81565b348015610a0757600080fd5b50610a1b610a163660046149b8565b612042565b6040516104c7929190615083565b348015610a3557600080fd5b50610a3e6120d3565b60405162ffffff90911681526020016104c7565b348015610a5e57600080fd5b506104f06120f1565b348015610a7357600080fd5b506104a3610a823660046150e3565b61211f565b348015610a9357600080fd5b506104a3610aa2366004615177565b612224565b348015610ab357600080fd5b50610ac7610ac23660046149b8565b6123f5565b6040805182516001600160a01b0316815260209283015162ffffff1692810192909252016104c7565b348015610afc57600080fd5b50610610610b0b366004614bea565b612489565b348015610b1c57600080fd5b50610a3e6124bf565b348015610b3157600080fd5b5061056763152a902d60e11b81565b348015610b4c57600080fd5b506104ba6124ed565b348015610b6157600080fd5b506104a36105903660046151d0565b348015610b7c57600080fd5b506104a3610b8b36600461521b565b61250a565b6104a3610b9e366004614b1f565b6125b9565b348015610baf57600080fd5b50610bc3610bbe3660046149b8565b61261d565b6040516104c79190615249565b348015610bdc57600080fd5b506104a3610beb366004614930565b612726565b348015610bfc57600080fd5b506104a3610c0b366004614e57565b6127fe565b348015610c1c57600080fd5b506104a3612820565b348015610c3157600080fd5b5047610567565b348015610c4457600080fd5b506104a3610c533660046152c6565b61283f565b348015610c6457600080fd5b506104a3610c73366004614930565b61288c565b348015610c8457600080fd5b50610567610c933660046149b8565b6128cf565b348015610ca457600080fd5b506104a3610cb33660046149b8565b6129b8565b348015610cc457600080fd5b506104ba610cd33660046149b8565b612a08565b348015610ce457600080fd5b506104a3610cf3366004615389565b612b47565b348015610d0457600080fd5b506104a3610d13366004614bea565b612b66565b348015610d2457600080fd5b50610610610d333660046149b8565b612b7d565b348015610d4457600080fd5b50610d58610d5336600461540c565b612baa565b6040516104c79190600060c0820190508251825260ff6020840151166020830152604083015162ffffff80821660408501526060850151915063ffffffff8083166060860152806080870151166080860152508060a08601511660a0850152505092915050565b348015610dcb57600080fd5b506104a3610dda366004615487565b612c9a565b348015610deb57600080fd5b50610a3e620f424081565b348015610e0257600080fd5b50610610610e11366004615560565b612d20565b348015610e2257600080fd5b506104a3612d5f565b348015610e3757600080fd5b506104a3610e46366004614930565b612d7e565b348015610e5757600080fd5b506104f0612db6565b348015610e6c57600080fd5b50610e80610e7b3660046149b8565b612dd4565b604080519283526020830191909152016104c7565b348015610ea157600080fd5b506104a3610eb0366004614930565b612e29565b348015610ec157600080fd5b50610567635b5e139f60e01b81565b610ee7600080516020615b9d833981519152612eb0565b6000610ef1612ed6565b600f0180546001600160a01b0319166001600160a01b03939093169290921790915550565b60606000610f22612ed6565b9050806001018054610f339061558e565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5f9061558e565b8015610fac5780601f10610f8157610100808354040283529160200191610fac565b820191906000526020600020905b815481529060010190602001808311610f8f57829003601f168201915b505050505091505090565b6000610fc282612efa565b610fdf57604051630cbdb7b360e41b815260040160405180910390fd5b6000610fe9612ed6565b9050610ff483613000565b6110115760405163538fd4df60e01b815260040160405180910390fd5b60009283526005016020525060409020546001600160a01b031690565b8161103881613179565b600061104383611ab7565b9050336001600160a01b03851614806110775750336001600160a01b0382161480159061107757506110758133612d20565b155b1561109557604051631eb49d6d60e11b815260040160405180910390fd5b61109f8484613227565b50505050565b6000806110b0612ed6565b600901546001600160a01b031692915050565b6110da600080516020615b9d833981519152612eb0565b6110e3816132a5565b50565b6000806110f1612ed6565b9050600060015b82546001600160401b031681101561113157611113816128cf565b61111d90836155de565b915061112a6001826155de565b90506110f8565b5092915050565b61114f600080516020615b9d833981519152612eb0565b6111576132e4565b505050565b611173600080516020615b9d833981519152612eb0565b600061117d612ed6565b600e0180546001600160a01b0319166001600160a01b03939093169290921790915550565b826001600160a01b03811633146111bc576111bc33613179565b6111c63383613314565b6111e3576040516313ff771f60e21b815260040160405180910390fd5b61109f848484613392565b6000611208600080516020615b9d83398151915283612489565b92915050565b600080611219612ed6565b805490915060009061123790600160401b900462ffffff16866155f6565b905061124384826155de565b95945050505050565b61125b898989898989876133e2565b61126a8762ffffff168561363f565b60006112778a8686613683565b9050611282816138bf565b50505050505050505050565b600080600061129b612ed6565b60098101546040516329c5eaf560e11b815230600482015260248101889052604481018790529192506001600160a01b03169063538bd5ea906064016040805180830381865afa1580156112f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113179190615615565b92509250505b9250929050565b61133b600080516020615b9d833981519152612eb0565b6113458282613a23565b5050565b61135161486a565b600061135b612ed6565b80549091506001600160401b031683111561138957604051631a3973a960e01b815260040160405180910390fd5b6040805160008581526003840160209081528382206101a0840185525462ffffff8082168587019081526301000000830482166060870152600160301b830482166080870152600160481b8304821660a087015263ffffffff600160601b8404811660c0880152600160801b84041660e087015260ff600160a01b84048116610100880152600160a81b840481161515610120880152600160b01b84048316610140880152600160c81b8404909216610160870152600160e01b9092041615156101808501528352868252600b850181529290208054919283019161146d9061558e565b80601f01602080910402602001604051908101604052809291908181526020018280546114999061558e565b80156114e65780601f106114bb576101008083540402835291602001916114e6565b820191906000526020600020905b8154815290600101906020018083116114c957829003601f168201915b5050505050815250915050919050565b61150d600080516020615b9d833981519152612eb0565b6000611517612ed6565b60090180546001600160a01b0319166001600160a01b03939093169290921790915550565b6001600160a01b038116331461156457604051623fff3d60e91b815260040160405180910390fd5b6113458282613a97565b6000611587600080516020615b9d833981519152612eb0565b61158f6132e4565b9a9950505050505050505050565b826115a781611b11565b6115c45760405163589ed34b60e01b815260040160405180910390fd5b6115cc613b09565b60006115d78561261d565b905060006115e4866123f5565b90506115f586868460c00151613b56565b6115fe81613c22565b611611816020015162ffffff168661363f565b600061161e878787613683565b9050611629816138bf565b611634878783613c5e565b50505050505050565b826001600160a01b03811633146116575761165733613179565b61109f8484846040518060200160405280600081525061283f565b600061167c612ed6565b9050600061168983611ab7565b90506116953384613314565b6116b2576040516313ff771f60e21b815260040160405180910390fd5b6116bf8161dead85613d77565b60405183906000906001600160a01b03841690600080516020615bbd833981519152908390a460006116f084612dd4565b50600081815260038501602052604090208054919250600191600690611723908490600160301b900462ffffff16615643565b92506101000a81548162ffffff021916908362ffffff16021790555050505050565b61175c600080516020615b9d833981519152612eb0565b6000611766613fd5565b90506117718861261d565b5060008888888560405160200161178b949392919061566a565b60408051601f19818403018152918152815160209283012060008181529285905291206001015490915060ff16156117d65760405163ad983fdf60e01b815260040160405180910390fd5b63ffffffff8516158015906117f657508563ffffffff168563ffffffff16105b1561181457604051633e9d06f360e11b815260040160405180910390fd5b6040805160c08101825294855260ff988916602080870191825262ffffff998a1687840190815263ffffffff998a1660608901908152988a1660808901908152968b1660a08901908152600095865295909152919092209451855590516001909401805491519551935192519490981663ffffffff199091161761010094871694909402939093176bffffffffffffffff000000001916600160201b9185169190910263ffffffff60401b191617600160401b92909316919091029190911762ffffff60601b1916600160601b919092160217905550565b611903600080516020615b9d833981519152612eb0565b61190b613ff9565b565b8261191781611b11565b6119345760405163589ed34b60e01b815260040160405180910390fd5b61193c613b09565b60006119478561261d565b905061195885858360c00151613b56565b61196b816060015162ffffff168561363f565b6000611978868686613683565b9050611983816138bf565b505050505050565b6119a2600080516020615b9d833981519152612eb0565b60648211156119c457604051637e1d76fb60e01b815260040160405180910390fd5b60005b82811015611a1357611a0085838686858181106119e6576119e66156a7565b90506020020160208101906119fb9190614930565b613683565b5080611a0b816156bd565b9150506119c7565b5050505050565b600080611a25612ed6565b8054909150611a3f906001906001600160401b03166156d6565b6001600160401b031691505090565b600080611a59612ed6565b905060008484604051602001611a709291906156fe565b60408051601f1981840301815291815281516020928301206000908152600c9094019091529091205491505092915050565b600080611aad614054565b5460ff1692915050565b600080611ac383614078565b509392505050565b611ae2600080516020615b9d833981519152612eb0565b6000611aec612ed6565b600d0180546001600160a01b0319166001600160a01b03939093169290921790915550565b600080611b1d8361261d565b90506000816080015163ffffffff16600014158015611b46575042826080015163ffffffff1611155b8015611b6d575060a082015163ffffffff161580611b6d5750428260a0015163ffffffff16115b949350505050565b60005b81811015611157576000838383818110611b9457611b946156a7565b905060200201359050611ba681611672565b5080611bb1816156bd565b915050611b78565b600080611bc4612ed6565b600e01546001600160a01b031692915050565b600080611be2612ed6565b6001600160a01b03909316600090815260069093016020525050604090205490565b611c1b600080516020615b9d833981519152612eb0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611c68576040519150601f19603f3d011682016040523d82523d6000602084013e611c6d565b606091505b505090508061115757604051630f9310f960e01b815260040160405180910390fd5b611ca6600080516020615b9d833981519152612eb0565b6000611cb0613fd5565b9050611cbb8b61261d565b5060008b8b8b86604051602001611cd5949392919061566a565b6040516020818303038152906040528051906020012060001c9050611cf861488a565b8960ff168c60ff16141580611d1757508862ffffff168b62ffffff1614155b80611d2c57508362ffffff168562ffffff1614155b15611f22576040518060c00160405280878152602001600060ff1681526020018a62ffffff1681526020018963ffffffff1681526020018863ffffffff1681526020018562ffffff168152508360000160008481526020019081526020016000206000820151816000015560208201518160010160006101000a81548160ff021916908360ff16021790555060408201518160010160016101000a81548162ffffff021916908362ffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600101600c6101000a81548162ffffff021916908362ffffff1602179055509050508c8a8a86604051602001611e6a949392919061566a565b60408051808303601f1901815291815281516020928301206000818152868452829020845181559284015160019093018054928501516060860151608087015160a088015160ff90971663ffffffff199096169590951761010062ffffff93841602176bffffffffffffffff000000001916600160201b63ffffffff9283160263ffffffff60401b191617600160401b91909516029390931762ffffff60601b1916600160601b939094169290920292909217905591505b63ffffffff871615801590611f4257508763ffffffff168763ffffffff16105b15611f6057604051633e9d06f360e11b815260040160405180910390fd5b506040805160c08101825295865260ff998a16602080880191825262ffffff9a8b1688840190815263ffffffff9a8b1660608a01908152998b1660808a01908152968c1660a08a01908152600095865295909152919092209551865590516001909501805491519651935192518916600160601b0262ffffff60601b19938916600160401b0263ffffffff60401b1995909916600160201b02949094166bffffffffffffffff0000000019979099166101000263ffffffff19909216959099169490941793909317939093169490941792909217919091161790915550505050565b606080600061204f612ed6565b6009810154604051632e44189760e11b81529192506001600160a01b031690635c88312e906120849030908890600401614bd1565b600060405180830381865afa1580156120a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120c9919081019061577f565b9250925050915091565b6000806120de612ed6565b54600160401b900462ffffff1692915050565b7fcb8952d7e709d77cf862c59597b58044638bae7291440245a00835d98a0e72b3546001600160a01b031690565b7fe64551584c98548d769652536a405149aacacb81302f284a40bda60ebfbfbd3b805460ff16156121625760405162dc149f60e41b815260040160405180910390fd5b600061216c612ed6565b90506001810161217d888a83615889565b506002810161218d868883615889565b506009810180546001600160a01b0319166001600160a01b03851617905580546affffffffffffffffffffff19166a0f424000000000000000011781556121e2600080516020615b9d83398151915285613a23565b6121eb846140db565b61220873dab1a1854214684ace522439684a145e625052336132a5565b612210614103565b50805460ff19166001179055505050505050565b8361222e81611b11565b61224b5760405163589ed34b60e01b815260040160405180910390fd5b612253613b09565b600061225d612ed6565b9050600061226a8761261d565b905080610100015162ffffff1660001480612283575083155b156122a157604051630713314160e01b815260040160405180910390fd5b6101208101516000906122b99062ffffff168661595e565b90508662ffffff168110156122e157604051630713314160e01b815260040160405180910390fd5b600088336040516020016122f69291906156fe565b6040516020818303038152906040528051906020012060001c90508260c0015160ff1660001461236b5760c08301516000828152600c8601602052604090205460ff9091169061234c9062ffffff8b16906155de565b111561236b57604051635ac0a89b60e11b815260040160405180910390fd5b6000818152600c850160205260408120805462ffffff8b1692906123909084906155de565b90915550600090505b888461012001516123aa9190615972565b62ffffff168110156123e9576123d78888838181106123cb576123cb6156a7565b90506020020135611672565b806123e1816156bd565b915050612399565b50611282898933613683565b60408051808201909152600080825260208201526000612413612ed6565b80549091506001600160401b031683111561244157604051631a3973a960e01b815260040160405180910390fd5b60408051808201825260008581526010939093016020818152928420546001600160a01b038116835295909352918152600160a01b90930462ffffff16928101929092525090565b60008061249461417d565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b6000806124ca612ed6565b80549091506124e790600190600160401b900462ffffff1661599d565b91505090565b606060006124f9612ed6565b9050806002018054610f339061558e565b8161251481613179565b336001600160a01b0384160361253d57604051631eb49d6d60e11b815260040160405180910390fd5b6000612547612ed6565b33600081815260078301602090815260408083206001600160a01b038a1680855290835292819020805460ff1916891515908117909155905190815293945090927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b60006125c48a6123f5565b90506125d58a8a8a8a8a8a886133e2565b6125de81613c22565b6125ed8262ffffff168661363f565b60006125fa8b8787613683565b9050612605816138bf565b6126108b8783613c5e565b5050505050505050505050565b6126256148bf565b600061262f612ed6565b80549091506001600160401b031683111561265d57604051631a3973a960e01b815260040160405180910390fd5b60009283526003016020908152604092839020835161016081018552905462ffffff808216835263010000008204811693830193909352600160301b8104831694820194909452600160481b84048216606082015263ffffffff600160601b850481166080830152600160801b85041660a082015260ff600160a01b8504811660c0830152600160a81b85048116151560e0830152600160b01b85048316610100830152600160c81b8504909216610120820152600160e01b9093041615156101408301525090565b61273d600080516020615b9d833981519152612eb0565b60006127476141a1565b905060005b81548110156127ca5781600001818154811061276a5761276a6156a7565b6000918252602090912001546001600160a01b03908116908416036127b85781600001818154811061279e5761279e6156a7565b600091825260209091200180546001600160a01b03191690555b6127c36001826155de565b905061274c565b508054600181018255600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055565b612815600080516020615b9d833981519152612eb0565b61109f838383613683565b612837600080516020615b9d833981519152612eb0565b61190b6141c5565b836001600160a01b03811633146128595761285933613179565b6128633384613314565b61288057604051631eb49d6d60e11b815260040160405180910390fd5b611a1385858585614212565b6128a3600080516020615b9d833981519152612eb0565b60006128ad614229565b80546001600160a01b0319166001600160a01b03939093169290921790915550565b6000806128da612ed6565b6000848152600382016020908152604091829020825161016081018452905462ffffff8082168352630100000082048116938301849052600160301b82048116948301859052600160481b82048116606084015263ffffffff600160601b830481166080850152600160801b83041660a084015260ff600160a01b8304811660c0850152600160a81b83048116151560e0850152600160b01b83048216610100850152600160c81b8304909116610120840152600160e01b9091041615156101408201529293506129ab919061599d565b62ffffff16949350505050565b6129cf600080516020615b9d833981519152612eb0565b60006129d9612ed6565b60009283526003016020525060409020805460ff60e01b198116600160e01b9182900460ff1615909102179055565b6060612a1382612efa565b612a3057604051630cbdb7b360e41b815260040160405180910390fd5b6000612a3a612ed6565b90506000612a4784612dd4565b5090506000612a558261261d565b90508060e0015115612aa4576000828152600b840160205260409020612a7a8661424d565b604051602001612a8b9291906159b9565b6040516020818303038152906040529350505050919050565b6000828152600b8401602052604090208054612abf9061558e565b80601f0160208091040260200160405190810160405280929190818152602001828054612aeb9061558e565b8015612b385780601f10612b0d57610100808354040283529160200191612b38565b820191906000526020600020905b815481529060010190602001808311612b1b57829003601f168201915b50505050509350505050919050565b612b5e600080516020615b9d833981519152612eb0565b6116346132e4565b611564600080516020615b9d833981519152612eb0565b600080612b88612ed6565b6000938452600401602052505060409020546001600160a01b031661dead1490565b612bb261488a565b6000612bbc613fd5565b9050612bc78661261d565b50600086868686604051602001612be1949392919061566a565b60408051601f19818403018152918152815160209283012060008181529285905290822060018101549193509160ff9091169003612c325760405163c5723b5160e01b815260040160405180910390fd5b6040805160c0810182528254815260019092015460ff8116602084015262ffffff610100820481169284019290925263ffffffff600160201b820481166060850152600160401b8204166080840152600160601b90041660a082015292505050949350505050565b612cb1600080516020615b9d833981519152612eb0565b6000612cbb612ed6565b600981015460405163dfc9f91360e01b81529192506001600160a01b03169063dfc9f91390612cf290309033908790600401615a37565b600060405180830381600087803b158015612d0c57600080fd5b505af1158015611983573d6000803e3d6000fd5b600080612d2b612ed6565b6001600160a01b03948516600090815260079190910160209081526040808320959096168252939093525050205460ff1690565b612d76600080516020615b9d833981519152612eb0565b61190b614103565b612d8661434d565b6001600160a01b038116612dad57604051633a247dd760e11b815260040160405180910390fd5b6110e38161437d565b600080612dc1612ed6565b600d01546001600160a01b031692915050565b6000806000612de1612ed6565b8054909150612dfc90600160401b900462ffffff168561595e565b8154909350612e1790600160401b900462ffffff16846155f6565b612e219085615aba565b915050915091565b612e40600080516020615b9d833981519152612eb0565b60006001600160a01b03821647604051600081818185875af1925050503d8060008114612e89576040519150601f19603f3d011682016040523d82523d6000602084013e612e8e565b606091505b505090508061134557604051630f9310f960e01b815260040160405180910390fd5b612eba8133612489565b6110e357604051623fff3d60e91b815260040160405180910390fd5b7fbc7d0e8ed4dcaf65aa37ff076afe36b4e8fbc0e9b704cfd2ecde67415414d07a90565b6000806000612f0884612dd4565b91509150612f1584612b7d565b15612f24575060009392505050565b6000612f2e612ed6565b60009384526003016020908152604093849020845161016081018652905462ffffff8082168352630100000082048116938301849052600160301b8204811696830196909652600160481b81048616606083015263ffffffff600160601b820481166080840152600160801b82041660a083015260ff600160a01b8204811660c0840152600160a81b82048116151560e0840152600160b01b82048716610100840152600160c81b8204909616610120830152600160e01b900490941615156101409094019390935250111592915050565b60008061300b612ed6565b9050600061301884612dd4565b506000818152600384016020908152604091829020825161016081018452905462ffffff808216835263010000008204811693830193909352600160301b8104831693820193909352600160481b83048216606082015263ffffffff600160601b840481166080830152600160801b84041660a082015260ff600160a01b8404811660c0830152600160a81b84048116151560e0830152600160b01b84048316610100830152600160c81b8404909216610120820152600160e01b909204161580156101408301529192509061316e57600e830154604051633c29490960e21b8152600481018790526000916001600160a01b03169063f0a5242490602401602060405180830381865afa158015613134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131589190615ad1565b9050801561316c5750600095945050505050565b505b506001949350505050565b6000613183614229565b80549091506001600160a01b03163b15611345578054604051633185c44d60e21b81523060048201526001600160a01b0384811660248301529091169063c617113490604401602060405180830381865afa1580156131e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061320a9190615ad1565b61134557604051631eb49d6d60e11b815260040160405180910390fd5b6000613231612ed6565b6000838152600582016020526040902080546001600160a01b0319166001600160a01b038616908117909155909150829061326b82611ab7565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60006132af6141a1565b8054600181018255600091825260209091200180546001600160a01b0319166001600160a01b03939093169290921790915550565b60006132ee6143d6565b90503660008037600080366000845af43d6000803e80801561330f573d6000f35b3d6000fd5b600061331f82612efa565b61333c57604051630cbdb7b360e41b815260040160405180910390fd5b600061334783611ab7565b9050806001600160a01b0316846001600160a01b031614806133825750836001600160a01b031661337784610fb7565b6001600160a01b0316145b80611b6d5750611b6d8185612d20565b61339d838383614447565b6133a8600082613227565b80826001600160a01b0316846001600160a01b0316600080516020615bbd83398151915260405160405180910390a4611157838383613d77565b60006133ec612ed6565b905060006133fc89898986612baa565b9050600089336040516020016134139291906156fe565b6040516020818303038152906040528051906020012060001c9050816020015160ff168562ffffff1684600c0160008481526020019081526020016000205461345c91906155de565b111561347b57604051635ac0a89b60e11b815260040160405180910390fd5b606082015163ffffffff16158061349b5750816060015163ffffffff1642105b156134b95760405163589ed34b60e01b815260040160405180910390fd5b608082015163ffffffff16158015906134db5750816080015163ffffffff1642115b156134f95760405163589ed34b60e01b815260040160405180910390fd5b6040516001600160601b03193360601b16602082015260009060340160405160208183030381529060405280519060200120905061356d888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508651915084905061446d565b1580156135ea5750600d8401546040516370a0823160e01b81526001600160a01b03909116906370a08231906135a79033906004016149d1565b602060405180830381865afa1580156135c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e89190615aee565b155b1561360857604051630b094f2760e31b815260040160405180910390fd5b6000828152600c850160205260408120805462ffffff8916929061362d9084906155de565b90915550505050505050505050505050565b60006136528366038d7ea4c680006155f6565b90503461366462ffffff8416836155f6565b11156111575760405163356680b760e01b815260040160405180910390fd5b60008061368e612ed6565b600086815260038201602052604081208054929350916136bb906301000000900462ffffff166001615643565b835462ffffff9190911691506001600160401b03168711156136f057604051631a3973a960e01b815260040160405180910390fd5b62ffffff8616158061370957506001600160a01b038516155b156137275760405163b732d5e160e01b815260040160405180910390fd5b815462ffffff1681111561374e57604051631f6e464360e31b815260040160405180910390fd5b613758878261120e565b825490945062ffffff808216916137789189916301000000900416615643565b62ffffff16111561379c57604051631f6e464360e31b815260040160405180910390fd5b8154869083906003906137bc9084906301000000900462ffffff16615643565b82546101009290920a62ffffff818102199093169190921691909102179055506000848152600484016020526040902080546001600160a01b0319166001600160a01b0387161790556138126008840185614485565b6001600160a01b03851660009081526006840160205260408120805462ffffff891692906138419084906155de565b909155508490505b61385862ffffff8816866155de565b8110156138b45760405181906001600160a01b03881690600090600080516020615bbd833981519152908290a46138a160008783604051806020016040528060008152506144b1565b50806138ac816156bd565b915050613849565b505050509392505050565b60006138c9612ed6565b6009810154604051632e44189760e11b815291925060009182916001600160a01b031690635c88312e906139039030908890600401614bd1565b600060405180830381865afa158015613920573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613948919081019061577f565b8151919350915060005b8181101561198357600061397f34858481518110613972576139726156a7565b60200260200101516145b0565b90506000858381518110613995576139956156a7565b60200260200101516001600160a01b03168260405160006040518083038185875af1925050503d80600081146139e7576040519150601f19603f3d011682016040523d82523d6000602084013e6139ec565b606091505b5050905080613a0e57604051630f9310f960e01b815260040160405180910390fd5b50508080613a1b906156bd565b915050613952565b6000613a2d61417d565b9050613a398383612489565b611157576000838152602082815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339286917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a4505050565b6000613aa161417d565b9050613aad8383612489565b15611157576000838152602082815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4505050565b613b11611aa2565b1561190b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b6000613b60612ed6565b905060ff821615801590613b795750613b776145c9565b155b1561109f5760008433604051602001613b939291906156fe565b60408051601f1981840301815291815281516020928301206000818152600c860190935291205490915060ff841690613bd29062ffffff8716906155de565b1115613bf157604051635ac0a89b60e11b815260040160405180910390fd5b6000818152600c830160205260408120805462ffffff87169290613c169084906155de565b90915550505050505050565b80516001600160a01b03161580613c405750602081015162ffffff16155b156110e3576040516306d423a960e21b815260040160405180910390fd5b6000613c68612ed6565b60008581526010820160205260408120549192506001600160a01b039091169062ffffff85166001600160401b03811115613ca557613ca5615258565b604051908082528060200260200182016040528015613cce578160200160208202803683370190505b50905060005b8562ffffff16811015613d1a57613ceb81866155de565b828281518110613cfd57613cfd6156a7565b602090810291909101015280613d12816156bd565b915050613cd4565b50604051630adf035760e41b81526001600160a01b0383169063adf0357090613d499032908590600401615b07565b600060405180830381600087803b158015613d6357600080fd5b505af1158015611282573d6000803e3d6000fd5b6000613d81612ed6565b90506000613d8e83614078565b9150506000613d9c84611ab7565b9050856001600160a01b0316816001600160a01b031614613dd0576040516313ff771f60e21b815260040160405180910390fd5b6000613ddd8560016155de565b90506000613dea82612dd4565b9150506000613df887612dd4565b506000818152600388016020908152604091829020825161016081018452905462ffffff80821680845263010000008304821694840194909452600160301b8204811694830194909452600160481b81048416606083015263ffffffff600160601b820481166080840152600160801b82041660a083015260ff600160a01b8204811660c0840152600160a81b82048116151560e0840152600160b01b82048516610100840152600160c81b8204909416610120830152600160e01b90049092161515610140830152919250908311801590613ef15750600884811c60009081529088016020526040902054600160ff1b60ff86161c16155b15613f2c576000848152600488016020526040902080546001600160a01b0319166001600160a01b038c16179055613f2c6008880185614485565b6000888152600488016020526040902080546001600160a01b0319166001600160a01b038b16179055858814613f6957613f696008880189614485565b6001600160a01b03891660009081526006880160205260408120805460019290613f949084906155de565b90915550506001600160a01b038a1660009081526006880160205260408120805460019290613fc4908490615aba565b909155505050505050505050505050565b7f5cdb56131f6a8cb8897cc0bafef07a5b2973e186f281253cea0806ea1443c13e90565b614001613b09565b600061400b614054565b805460ff191660011781556040519091507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906140499033906149d1565b60405180910390a150565b7f2ce935bb7ebbf5d9759d0bf10b40148186ea48e69aeea9281cb4f3267f07abf390565b60008061408483612efa565b6140a157604051630cbdb7b360e41b815260040160405180910390fd5b60006140ab612ed6565b90506140b684614636565b600081815260049092016020526040909120546001600160a01b031694909350915050565b60007fcb8952d7e709d77cf862c59597b58044638bae7291440245a00835d98a0e72b36128ad565b600061410d614229565b80546001600160a01b0319166daaeb6d7670e522a718067333cd4e9081178255909150803b1561134557604051633e9f1edf60e11b8152306004820152733cc6cdda760b79bafa08df41ecfa224f810dceb660248201526001600160a01b03821690637d3e3dbe90604401612cf2565b7f8113889f0b868eeca4f3f98876bebc5d45f78186a7ac12c94ed39d8b17ef258e90565b7f92140bce112f095179820a95d551eb064f38e1596fa0b63a05d6960156840a9a90565b6141cd61467b565b60006141d7614054565b805460ff191681556040519091507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906140499033906149d1565b61421d848484613392565b611a13848484846144b1565b7fd1c7a1698d3d2d2fdb5cc2360b499ff16d810b81a494d1feedda8dbe4b67fb7890565b6060816000036142745750506040805180820190915260018152600360fc1b602082015290565b8160005b811561429e5780614288816156bd565b91506142979050600a8361595e565b9150614278565b6000816001600160401b038111156142b8576142b8615258565b6040519080825280601f01601f1916602001820160405280156142e2576020820181803683370190505b5090505b8415611b6d576142f7600183615aba565b9150614304600a86615b2b565b61430f9060306155de565b60f81b818381518110614324576143246156a7565b60200101906001600160f81b031916908160001a905350614346600a8661595e565b94506142e6565b336143566120f1565b6001600160a01b03161461190b57604051636db2465f60e01b815260040160405180910390fd5b60006143876120f1565b9050614392826140db565b816001600160a01b0316816001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000806143e1612ed6565b600f8101549091506001600160a01b03161561440957600f01546001600160a01b0316919050565b4660050361442c5773bb7093937225983269a7003e15a7b8200f8b523d91505090565b73e291354a3aeb7eb49da0f1333d667f17fa33f1c591505090565b61445081613000565b6111575760405163538fd4df60e01b815260040160405180910390fd5b60008261447a85846146c6565b1490505b9392505050565b600881901c600090815260209290925260409091208054600160ff1b60ff9093169290921c9091179055565b60006001600160a01b0384163b156145a857604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906144f5903390899088908890600401615b3f565b6020604051808303816000875af1925050508015614530575060408051601f3d908101601f1916820190925261452d91810190615b72565b60015b61458e573d80801561455e576040519150601f19603f3d011682016040523d82523d6000602084013e614563565b606091505b50805160000361458657604051630568cbab60e01b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611b6d565b506001611b6d565b60006127106145bf83856155f6565b61447e919061595e565b6000806145d46141a1565b905060005b815481101561462d578160000181815481106145f7576145f76156a7565b6000918252602090912001546001600160a01b0316330361461b5760019250505090565b6146266001826155de565b90506145d9565b50600091505090565b600080614641612ed6565b9050600061464e84612dd4565b508254909150611b6d90859061467090600160401b900462ffffff16846155f6565b60088501919061470b565b614683611aa2565b61190b5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401613b4d565b600081815b8451811015611ac3576146f7828683815181106146ea576146ea6156a7565b60200260200101516147b9565b915080614703816156bd565b9150506146cb565b600882811c600081815260208690526040812054909284901c9060ff808716919082181c80156147545761473e816147e8565b60ff168203600885901b1794505050505061447e565b8284101561477557604051630f78a15d60e31b815260040160405180910390fd5b5060001990920160008181526020889052604090205490929080156147b45761479d816147e8565b60ff0360ff16600885901b1794505050505061447e565b614754565b60008183106147d557600082815260208490526040902061447e565b600083815260208390526040902061447e565b60006040518061012001604052806101008152602001615bdd610100913960f87e818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff61483185614852565b02901c81518110614844576148446156a7565b016020015160f81c92915050565b600080821161486057600080fd5b5060008190031690565b604051806040016040528061487d6148bf565b8152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915290565b6001600160a01b03811681146110e357600080fd5b60006020828403121561494257600080fd5b813561447e8161491b565b60005b83811015614968578181015183820152602001614950565b8381111561109f5750506000910152565b6000815180845261499181602086016020860161494d565b601f01601f19169290920160200192915050565b60208152600061447e6020830184614979565b6000602082840312156149ca57600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600080604083850312156149f857600080fd5b8235614a038161491b565b946020939093013593505050565b803562ffffff81168114614a2457600080fd5b919050565b600080600060608486031215614a3e57600080fd5b833592506020840135614a508161491b565b9150614a5e60408501614a11565b90509250925092565b600080600060608486031215614a7c57600080fd5b8335614a878161491b565b92506020840135614a978161491b565b929592945050506040919091013590565b60008060408385031215614abb57600080fd5b50508035926020909101359150565b803560ff81168114614a2457600080fd5b60008083601f840112614aed57600080fd5b5081356001600160401b03811115614b0457600080fd5b6020830191508360208260051b850101111561131d57600080fd5b60008060008060008060008060006101008a8c031215614b3e57600080fd5b89359850614b4e60208b01614aca565b9750614b5c60408b01614a11565b965060608a01356001600160401b03811115614b7757600080fd5b614b838c828d01614adb565b9097509550614b96905060808b01614a11565b935060a08a0135614ba68161491b565b9250614bb460c08b01614a11565b9150614bc260e08b01614a11565b90509295985092959850929598565b6001600160a01b03929092168252602082015260400190565b60008060408385031215614bfd57600080fd5b823591506020830135614c0f8161491b565b809150509250929050565b805162ffffff1682526020810151614c39602084018262ffffff169052565b506040810151614c50604084018262ffffff169052565b506060810151614c67606084018262ffffff169052565b506080810151614c7f608084018263ffffffff169052565b5060a0810151614c9760a084018263ffffffff169052565b5060c0810151614cac60c084018260ff169052565b5060e0810151614cc060e084018215159052565b506101008181015162ffffff81168483015250506101208181015162ffffff8116848301525050610140818101518015158483015261109f565b60208152614d0c602082018351614c1a565b602082015161018082810152600090611b6d6101a0840182614979565b60008083601f840112614d3b57600080fd5b5081356001600160401b03811115614d5257600080fd5b60208301915083602082850101111561131d57600080fd5b803563ffffffff81168114614a2457600080fd5b80151581146110e357600080fd5b6000806000806000806000806000806101208b8d031215614dac57600080fd5b8a356001600160401b03811115614dc257600080fd5b614dce8d828e01614d29565b909b509950614de1905060208c01614a11565b9750614def60408c01614a11565b9650614dfd60608c01614d6a565b9550614e0b60808c01614d6a565b9450614e1960a08c01614aca565b935060c08b0135614e2981614d7e565b9250614e3760e08c01614aca565b9150614e466101008c01614aca565b90509295989b9194979a5092959850565b600080600060608486031215614e6c57600080fd5b83359250614e7c60208501614a11565b91506040840135614e8c8161491b565b809150509250925092565b600080600080600080600060e0888a031215614eb257600080fd5b87359650614ec260208901614aca565b9550614ed060408901614a11565b9450614ede60608901614d6a565b9350614eec60808901614d6a565b925060a08801359150614f0160c08901614a11565b905092959891949750929550565b60008060008060608587031215614f2557600080fd5b8435935060208501356001600160401b03811115614f4257600080fd5b614f4e87828801614adb565b9094509250614f61905060408601614a11565b905092959194509250565b60008060208385031215614f7f57600080fd5b82356001600160401b03811115614f9557600080fd5b614fa185828601614adb565b90969095509350505050565b6000806000806000806000806000806101408b8d031215614fcd57600080fd5b8a359950614fdd60208c01614aca565b9850614feb60408c01614a11565b9750614ff960608c01614aca565b965061500760808c01614a11565b955061501560a08c01614d6a565b945061502360c08c01614d6a565b935060e08b013592506150396101008c01614a11565b9150614e466101208c01614a11565b600081518084526020808501945080840160005b838110156150785781518752958201959082019060010161505c565b509495945050505050565b604080825283519082018190526000906020906060840190828701845b828110156150c55781516001600160a01b0316845292840192908401906001016150a0565b505050838103828501526150d98186615048565b9695505050505050565b600080600080600080608087890312156150fc57600080fd5b86356001600160401b038082111561511357600080fd5b61511f8a838b01614d29565b9098509650602089013591508082111561513857600080fd5b5061514589828a01614d29565b90955093505060408701356151598161491b565b915060608701356151698161491b565b809150509295509295509295565b6000806000806060858703121561518d57600080fd5b8435935061519d60208601614a11565b925060408501356001600160401b038111156151b857600080fd5b6151c487828801614adb565b95989497509550505050565b6000806000604084860312156151e557600080fd5b8335925060208401356001600160401b0381111561520257600080fd5b61520e86828701614d29565b9497909650939450505050565b6000806040838503121561522e57600080fd5b82356152398161491b565b91506020830135614c0f81614d7e565b61016081016112088284614c1a565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561529057615290615258565b60405290565b604051601f8201601f191681016001600160401b03811182821017156152be576152be615258565b604052919050565b600080600080608085870312156152dc57600080fd5b84356152e78161491b565b93506020858101356152f88161491b565b93506040860135925060608601356001600160401b038082111561531b57600080fd5b818801915088601f83011261532f57600080fd5b81358181111561534157615341615258565b615353601f8201601f19168501615296565b9150808252898482850101111561536957600080fd5b808484018584013760008482840101525080935050505092959194509250565b600080600080600080600060e0888a0312156153a457600080fd5b873596506153b460208901614a11565b95506153c260408901614d6a565b94506153d060608901614d6a565b93506153de60808901614aca565b92506153ec60a08901614a11565b915060c08801356153fc81614d7e565b8091505092959891949750929550565b6000806000806080858703121561542257600080fd5b8435935061543260208601614aca565b925061544060408601614a11565b9150614f6160608601614a11565b60006001600160401b0382111561546757615467615258565b5060051b60200190565b803565ffffffffffff81168114614a2457600080fd5b6000602080838503121561549a57600080fd5b82356001600160401b038111156154b057600080fd5b8301601f810185136154c157600080fd5b80356154d46154cf8261544e565b615296565b818152606091820283018401918482019190888411156154f357600080fd5b938501935b838510156155545780858a0312156155105760008081fd5b61551861526e565b85356155238161491b565b8152615530868801615471565b878201526040615541818801615471565b90820152835293840193918501916154f8565b50979650505050505050565b6000806040838503121561557357600080fd5b823561557e8161491b565b91506020830135614c0f8161491b565b600181811c908216806155a257607f821691505b6020821081036155c257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082198211156155f1576155f16155c8565b500190565b6000816000190483118215151615615610576156106155c8565b500290565b6000806040838503121561562857600080fd5b82516156338161491b565b6020939093015192949293505050565b600062ffffff808316818516808303821115615661576156616155c8565b01949350505050565b93845260f89290921b6001600160f81b031916602084015260e890811b6001600160e81b0319908116602185015291901b16602482015260270190565b634e487b7160e01b600052603260045260246000fd5b6000600182016156cf576156cf6155c8565b5060010190565b60006001600160401b03838116908316818110156156f6576156f66155c8565b039392505050565b91825260601b6001600160601b031916602082015260340190565b600082601f83011261572a57600080fd5b8151602061573a6154cf8361544e565b82815260059290921b8401810191818101908684111561575957600080fd5b8286015b84811015615774578051835291830191830161575d565b509695505050505050565b6000806040838503121561579257600080fd5b82516001600160401b03808211156157a957600080fd5b818501915085601f8301126157bd57600080fd5b815160206157cd6154cf8361544e565b82815260059290921b840181019181810190898411156157ec57600080fd5b948201945b838610156158135785516158048161491b565b825294820194908201906157f1565b9188015191965090935050508082111561582c57600080fd5b5061583985828601615719565b9150509250929050565b601f82111561115757600081815260208120601f850160051c8101602086101561586a5750805b601f850160051c820191505b8181101561198357828155600101615876565b6001600160401b038311156158a0576158a0615258565b6158b4836158ae835461558e565b83615843565b6000601f8411600181146158e857600085156158d05750838201355b600019600387901b1c1916600186901b178355611a13565b600083815260209020601f19861690835b8281101561591957868501358255602094850194600190920191016158f9565b50868210156159365760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b600052601260045260246000fd5b60008261596d5761596d615948565b500490565b600062ffffff80831681851681830481118215151615615994576159946155c8565b02949350505050565b600062ffffff838116908316818110156156f6576156f66155c8565b60008084546159c78161558e565b600182811680156159df57600181146159f457615a23565b60ff1984168752821515830287019450615a23565b8860005260208060002060005b85811015615a1a5781548a820152908401908201615a01565b50505082870194505b50505050835161566181836020880161494d565b6000606080830160018060a01b03808816855260208188168187015260408481880152838851808652608089019150838a01955060005b81811015615aa95786518051871684528581015165ffffffffffff908116878601529085015116848401529584019591870191600101615a6e565b50909b9a5050505050505050505050565b600082821015615acc57615acc6155c8565b500390565b600060208284031215615ae357600080fd5b815161447e81614d7e565b600060208284031215615b0057600080fd5b5051919050565b6001600160a01b0383168152604060208201819052600090611b6d90830184615048565b600082615b3a57615b3a615948565b500690565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906150d990830184614979565b600060208284031215615b8457600080fd5b81516001600160e01b03198116811461447e57600080fdfeea8e1b953cb200117b202dd78c6958f9c14d952d5bdaa146141d2a5f9ee220dbddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8a264697066735822122094f5a18949d67f99a8b61c9a18164969a23e742579a40a85088eb229ec7f3f7064736f6c634300080f0033
Deployed Bytecode
0x60806040526004361061047e5760003560e01c806370d5ae0511610255578063ae005af911610144578063db44fe07116100c1578063eb44774011610085578063eb44774014610e16578063f2fde38b14610e2b578063f343958f14610e4b578063f45e3ebd14610e60578063fa09e63014610e95578063fc45635314610eb557600080fd5b8063db44fe0714610d18578063dc47a41014610d38578063e18827cd14610dbf578063e720a4b014610ddf578063e985e9c514610df657600080fd5b8063be5dea8a11610108578063be5dea8a14610c78578063c6879ff914610c98578063c87b56dd14610cb8578063d49232a114610cd8578063d547741f14610cf857600080fd5b8063ae005af914610bf0578063b33712c514610c10578063b69ef8a814610c25578063b88d4fde14610c38578063b8d1e53214610c5857600080fd5b8063910eec1f116101d2578063999873f711610196578063999873f714610b55578063a22cb46514610b70578063a34931c114610b90578063a642c03214610ba3578063a9359de814610bd057600080fd5b8063910eec1f14610aa757806391d1485414610af0578063933a261114610b10578063946a3cbb14610b2557806395d89b4114610b4057600080fd5b80637f12460f116102195780637f12460f146109fb57806380cd807c14610a295780638da5cb5b14610a525780638f15b41414610a675780638fc614ec14610a8757600080fd5b806370d5ae0514610962578063736fe5651461097857806373d31507146109985780637b56fc59146109b85780637cb796eb146109e057600080fd5b80633596b4ac1161037157806351d329dc116102ee57806363a5c0eb116102b257806363a5c0eb146108cd57806365308579146108ed5780636ab49a5b1461090d5780636afe57951461092d57806370a082311461094257600080fd5b806351d329dc1461084e57806357c49277146108635780635b353be2146108835780635c975abb146108985780636352211e146108ad57600080fd5b806342966c681161033557806342966c68146107c6578063434e3603146107e6578063439766ce146108065780634cb30db11461081b5780634d213ff11461082e57600080fd5b80633596b4ac1461072b57806336568abe146107535780633cbb1bb2146107735780633ebd45861461079357806342842e0e146107a657600080fd5b806323b872dd116103ff5780632a55205a116103c35780632a55205a1461066e5780632f2ff15d1461069c578063322ff140146106bc5780633474bd1e146106e957806335742d741461070957600080fd5b806323b872dd146105d057806324d7806c146105f057806325acc72e1461062057806328205b2f14610640578063287ea4341461065b57600080fd5b80630b213c07116104465780630b213c071461053257806318160ddd146105525780631a9968a9146105755780631c1f8aa3146105955780631e8f5530146105b557600080fd5b8063033da70b1461048357806306fdde03146104a5578063081812fc146104d0578063095ea7b3146104fd5780630a62f2141461051d575b600080fd5b34801561048f57600080fd5b506104a361049e366004614930565b610ed0565b005b3480156104b157600080fd5b506104ba610f16565b6040516104c791906149a5565b60405180910390f35b3480156104dc57600080fd5b506104f06104eb3660046149b8565b610fb7565b6040516104c791906149d1565b34801561050957600080fd5b506104a36105183660046149e5565b61102e565b34801561052957600080fd5b506104f06110a5565b34801561053e57600080fd5b506104a361054d366004614930565b6110c3565b34801561055e57600080fd5b506105676110e6565b6040519081526020016104c7565b34801561058157600080fd5b506104a3610590366004614a29565b611138565b3480156105a157600080fd5b506104a36105b0366004614930565b61115c565b3480156105c157600080fd5b506105676380ac58cd60e01b81565b3480156105dc57600080fd5b506104a36105eb366004614a67565b6111a2565b3480156105fc57600080fd5b5061061061060b366004614930565b6111ee565b60405190151581526020016104c7565b34801561062c57600080fd5b5061056761063b366004614aa8565b61120e565b34801561064c57600080fd5b50610567632483248360e11b81565b6104a3610669366004614b1f565b61124c565b34801561067a57600080fd5b5061068e610689366004614aa8565b61128e565b6040516104c7929190614bd1565b3480156106a857600080fd5b506104a36106b7366004614bea565b611324565b3480156106c857600080fd5b506106dc6106d73660046149b8565b611349565b6040516104c79190614cfa565b3480156106f557600080fd5b506104a3610704366004614930565b6114f6565b34801561071557600080fd5b50610567600080516020615b9d83398151915281565b34801561073757600080fd5b506104f073e291354a3aeb7eb49da0f1333d667f17fa33f1c581565b34801561075f57600080fd5b506104a361076e366004614bea565b61153c565b34801561077f57600080fd5b5061056761078e366004614d8c565b61156e565b6104a36107a1366004614e57565b61159d565b3480156107b257600080fd5b506104a36107c1366004614a67565b61163d565b3480156107d257600080fd5b506104a36107e13660046149b8565b611672565b3480156107f257600080fd5b506104a3610801366004614e97565b611745565b34801561081257600080fd5b506104a36118ec565b6104a3610829366004614e57565b61190d565b34801561083a57600080fd5b506104a3610849366004614f0f565b61198b565b34801561085a57600080fd5b50610567611a1a565b34801561086f57600080fd5b5061056761087e366004614bea565b611a4e565b34801561088f57600080fd5b50610567606481565b3480156108a457600080fd5b50610610611aa2565b3480156108b957600080fd5b506104f06108c83660046149b8565b611ab7565b3480156108d957600080fd5b506104a36108e8366004614930565b611acb565b3480156108f957600080fd5b506106106109083660046149b8565b611b11565b34801561091957600080fd5b506104a3610928366004614f6c565b611b75565b34801561093957600080fd5b506104f0611bb9565b34801561094e57600080fd5b5061056761095d366004614930565b611bd7565b34801561096e57600080fd5b506104f061dead81565b34801561098457600080fd5b506104a36109933660046149e5565b611c04565b3480156109a457600080fd5b506104a36109b3366004614fad565b611c8f565b3480156109c457600080fd5b506104f073bb7093937225983269a7003e15a7b8200f8b523d81565b3480156109ec57600080fd5b506105676301ffc9a760e01b81565b348015610a0757600080fd5b50610a1b610a163660046149b8565b612042565b6040516104c7929190615083565b348015610a3557600080fd5b50610a3e6120d3565b60405162ffffff90911681526020016104c7565b348015610a5e57600080fd5b506104f06120f1565b348015610a7357600080fd5b506104a3610a823660046150e3565b61211f565b348015610a9357600080fd5b506104a3610aa2366004615177565b612224565b348015610ab357600080fd5b50610ac7610ac23660046149b8565b6123f5565b6040805182516001600160a01b0316815260209283015162ffffff1692810192909252016104c7565b348015610afc57600080fd5b50610610610b0b366004614bea565b612489565b348015610b1c57600080fd5b50610a3e6124bf565b348015610b3157600080fd5b5061056763152a902d60e11b81565b348015610b4c57600080fd5b506104ba6124ed565b348015610b6157600080fd5b506104a36105903660046151d0565b348015610b7c57600080fd5b506104a3610b8b36600461521b565b61250a565b6104a3610b9e366004614b1f565b6125b9565b348015610baf57600080fd5b50610bc3610bbe3660046149b8565b61261d565b6040516104c79190615249565b348015610bdc57600080fd5b506104a3610beb366004614930565b612726565b348015610bfc57600080fd5b506104a3610c0b366004614e57565b6127fe565b348015610c1c57600080fd5b506104a3612820565b348015610c3157600080fd5b5047610567565b348015610c4457600080fd5b506104a3610c533660046152c6565b61283f565b348015610c6457600080fd5b506104a3610c73366004614930565b61288c565b348015610c8457600080fd5b50610567610c933660046149b8565b6128cf565b348015610ca457600080fd5b506104a3610cb33660046149b8565b6129b8565b348015610cc457600080fd5b506104ba610cd33660046149b8565b612a08565b348015610ce457600080fd5b506104a3610cf3366004615389565b612b47565b348015610d0457600080fd5b506104a3610d13366004614bea565b612b66565b348015610d2457600080fd5b50610610610d333660046149b8565b612b7d565b348015610d4457600080fd5b50610d58610d5336600461540c565b612baa565b6040516104c79190600060c0820190508251825260ff6020840151166020830152604083015162ffffff80821660408501526060850151915063ffffffff8083166060860152806080870151166080860152508060a08601511660a0850152505092915050565b348015610dcb57600080fd5b506104a3610dda366004615487565b612c9a565b348015610deb57600080fd5b50610a3e620f424081565b348015610e0257600080fd5b50610610610e11366004615560565b612d20565b348015610e2257600080fd5b506104a3612d5f565b348015610e3757600080fd5b506104a3610e46366004614930565b612d7e565b348015610e5757600080fd5b506104f0612db6565b348015610e6c57600080fd5b50610e80610e7b3660046149b8565b612dd4565b604080519283526020830191909152016104c7565b348015610ea157600080fd5b506104a3610eb0366004614930565b612e29565b348015610ec157600080fd5b50610567635b5e139f60e01b81565b610ee7600080516020615b9d833981519152612eb0565b6000610ef1612ed6565b600f0180546001600160a01b0319166001600160a01b03939093169290921790915550565b60606000610f22612ed6565b9050806001018054610f339061558e565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5f9061558e565b8015610fac5780601f10610f8157610100808354040283529160200191610fac565b820191906000526020600020905b815481529060010190602001808311610f8f57829003601f168201915b505050505091505090565b6000610fc282612efa565b610fdf57604051630cbdb7b360e41b815260040160405180910390fd5b6000610fe9612ed6565b9050610ff483613000565b6110115760405163538fd4df60e01b815260040160405180910390fd5b60009283526005016020525060409020546001600160a01b031690565b8161103881613179565b600061104383611ab7565b9050336001600160a01b03851614806110775750336001600160a01b0382161480159061107757506110758133612d20565b155b1561109557604051631eb49d6d60e11b815260040160405180910390fd5b61109f8484613227565b50505050565b6000806110b0612ed6565b600901546001600160a01b031692915050565b6110da600080516020615b9d833981519152612eb0565b6110e3816132a5565b50565b6000806110f1612ed6565b9050600060015b82546001600160401b031681101561113157611113816128cf565b61111d90836155de565b915061112a6001826155de565b90506110f8565b5092915050565b61114f600080516020615b9d833981519152612eb0565b6111576132e4565b505050565b611173600080516020615b9d833981519152612eb0565b600061117d612ed6565b600e0180546001600160a01b0319166001600160a01b03939093169290921790915550565b826001600160a01b03811633146111bc576111bc33613179565b6111c63383613314565b6111e3576040516313ff771f60e21b815260040160405180910390fd5b61109f848484613392565b6000611208600080516020615b9d83398151915283612489565b92915050565b600080611219612ed6565b805490915060009061123790600160401b900462ffffff16866155f6565b905061124384826155de565b95945050505050565b61125b898989898989876133e2565b61126a8762ffffff168561363f565b60006112778a8686613683565b9050611282816138bf565b50505050505050505050565b600080600061129b612ed6565b60098101546040516329c5eaf560e11b815230600482015260248101889052604481018790529192506001600160a01b03169063538bd5ea906064016040805180830381865afa1580156112f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113179190615615565b92509250505b9250929050565b61133b600080516020615b9d833981519152612eb0565b6113458282613a23565b5050565b61135161486a565b600061135b612ed6565b80549091506001600160401b031683111561138957604051631a3973a960e01b815260040160405180910390fd5b6040805160008581526003840160209081528382206101a0840185525462ffffff8082168587019081526301000000830482166060870152600160301b830482166080870152600160481b8304821660a087015263ffffffff600160601b8404811660c0880152600160801b84041660e087015260ff600160a01b84048116610100880152600160a81b840481161515610120880152600160b01b84048316610140880152600160c81b8404909216610160870152600160e01b9092041615156101808501528352868252600b850181529290208054919283019161146d9061558e565b80601f01602080910402602001604051908101604052809291908181526020018280546114999061558e565b80156114e65780601f106114bb576101008083540402835291602001916114e6565b820191906000526020600020905b8154815290600101906020018083116114c957829003601f168201915b5050505050815250915050919050565b61150d600080516020615b9d833981519152612eb0565b6000611517612ed6565b60090180546001600160a01b0319166001600160a01b03939093169290921790915550565b6001600160a01b038116331461156457604051623fff3d60e91b815260040160405180910390fd5b6113458282613a97565b6000611587600080516020615b9d833981519152612eb0565b61158f6132e4565b9a9950505050505050505050565b826115a781611b11565b6115c45760405163589ed34b60e01b815260040160405180910390fd5b6115cc613b09565b60006115d78561261d565b905060006115e4866123f5565b90506115f586868460c00151613b56565b6115fe81613c22565b611611816020015162ffffff168661363f565b600061161e878787613683565b9050611629816138bf565b611634878783613c5e565b50505050505050565b826001600160a01b03811633146116575761165733613179565b61109f8484846040518060200160405280600081525061283f565b600061167c612ed6565b9050600061168983611ab7565b90506116953384613314565b6116b2576040516313ff771f60e21b815260040160405180910390fd5b6116bf8161dead85613d77565b60405183906000906001600160a01b03841690600080516020615bbd833981519152908390a460006116f084612dd4565b50600081815260038501602052604090208054919250600191600690611723908490600160301b900462ffffff16615643565b92506101000a81548162ffffff021916908362ffffff16021790555050505050565b61175c600080516020615b9d833981519152612eb0565b6000611766613fd5565b90506117718861261d565b5060008888888560405160200161178b949392919061566a565b60408051601f19818403018152918152815160209283012060008181529285905291206001015490915060ff16156117d65760405163ad983fdf60e01b815260040160405180910390fd5b63ffffffff8516158015906117f657508563ffffffff168563ffffffff16105b1561181457604051633e9d06f360e11b815260040160405180910390fd5b6040805160c08101825294855260ff988916602080870191825262ffffff998a1687840190815263ffffffff998a1660608901908152988a1660808901908152968b1660a08901908152600095865295909152919092209451855590516001909401805491519551935192519490981663ffffffff199091161761010094871694909402939093176bffffffffffffffff000000001916600160201b9185169190910263ffffffff60401b191617600160401b92909316919091029190911762ffffff60601b1916600160601b919092160217905550565b611903600080516020615b9d833981519152612eb0565b61190b613ff9565b565b8261191781611b11565b6119345760405163589ed34b60e01b815260040160405180910390fd5b61193c613b09565b60006119478561261d565b905061195885858360c00151613b56565b61196b816060015162ffffff168561363f565b6000611978868686613683565b9050611983816138bf565b505050505050565b6119a2600080516020615b9d833981519152612eb0565b60648211156119c457604051637e1d76fb60e01b815260040160405180910390fd5b60005b82811015611a1357611a0085838686858181106119e6576119e66156a7565b90506020020160208101906119fb9190614930565b613683565b5080611a0b816156bd565b9150506119c7565b5050505050565b600080611a25612ed6565b8054909150611a3f906001906001600160401b03166156d6565b6001600160401b031691505090565b600080611a59612ed6565b905060008484604051602001611a709291906156fe565b60408051601f1981840301815291815281516020928301206000908152600c9094019091529091205491505092915050565b600080611aad614054565b5460ff1692915050565b600080611ac383614078565b509392505050565b611ae2600080516020615b9d833981519152612eb0565b6000611aec612ed6565b600d0180546001600160a01b0319166001600160a01b03939093169290921790915550565b600080611b1d8361261d565b90506000816080015163ffffffff16600014158015611b46575042826080015163ffffffff1611155b8015611b6d575060a082015163ffffffff161580611b6d5750428260a0015163ffffffff16115b949350505050565b60005b81811015611157576000838383818110611b9457611b946156a7565b905060200201359050611ba681611672565b5080611bb1816156bd565b915050611b78565b600080611bc4612ed6565b600e01546001600160a01b031692915050565b600080611be2612ed6565b6001600160a01b03909316600090815260069093016020525050604090205490565b611c1b600080516020615b9d833981519152612eb0565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114611c68576040519150601f19603f3d011682016040523d82523d6000602084013e611c6d565b606091505b505090508061115757604051630f9310f960e01b815260040160405180910390fd5b611ca6600080516020615b9d833981519152612eb0565b6000611cb0613fd5565b9050611cbb8b61261d565b5060008b8b8b86604051602001611cd5949392919061566a565b6040516020818303038152906040528051906020012060001c9050611cf861488a565b8960ff168c60ff16141580611d1757508862ffffff168b62ffffff1614155b80611d2c57508362ffffff168562ffffff1614155b15611f22576040518060c00160405280878152602001600060ff1681526020018a62ffffff1681526020018963ffffffff1681526020018863ffffffff1681526020018562ffffff168152508360000160008481526020019081526020016000206000820151816000015560208201518160010160006101000a81548160ff021916908360ff16021790555060408201518160010160016101000a81548162ffffff021916908362ffffff16021790555060608201518160010160046101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160086101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600101600c6101000a81548162ffffff021916908362ffffff1602179055509050508c8a8a86604051602001611e6a949392919061566a565b60408051808303601f1901815291815281516020928301206000818152868452829020845181559284015160019093018054928501516060860151608087015160a088015160ff90971663ffffffff199096169590951761010062ffffff93841602176bffffffffffffffff000000001916600160201b63ffffffff9283160263ffffffff60401b191617600160401b91909516029390931762ffffff60601b1916600160601b939094169290920292909217905591505b63ffffffff871615801590611f4257508763ffffffff168763ffffffff16105b15611f6057604051633e9d06f360e11b815260040160405180910390fd5b506040805160c08101825295865260ff998a16602080880191825262ffffff9a8b1688840190815263ffffffff9a8b1660608a01908152998b1660808a01908152968c1660a08a01908152600095865295909152919092209551865590516001909501805491519651935192518916600160601b0262ffffff60601b19938916600160401b0263ffffffff60401b1995909916600160201b02949094166bffffffffffffffff0000000019979099166101000263ffffffff19909216959099169490941793909317939093169490941792909217919091161790915550505050565b606080600061204f612ed6565b6009810154604051632e44189760e11b81529192506001600160a01b031690635c88312e906120849030908890600401614bd1565b600060405180830381865afa1580156120a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120c9919081019061577f565b9250925050915091565b6000806120de612ed6565b54600160401b900462ffffff1692915050565b7fcb8952d7e709d77cf862c59597b58044638bae7291440245a00835d98a0e72b3546001600160a01b031690565b7fe64551584c98548d769652536a405149aacacb81302f284a40bda60ebfbfbd3b805460ff16156121625760405162dc149f60e41b815260040160405180910390fd5b600061216c612ed6565b90506001810161217d888a83615889565b506002810161218d868883615889565b506009810180546001600160a01b0319166001600160a01b03851617905580546affffffffffffffffffffff19166a0f424000000000000000011781556121e2600080516020615b9d83398151915285613a23565b6121eb846140db565b61220873dab1a1854214684ace522439684a145e625052336132a5565b612210614103565b50805460ff19166001179055505050505050565b8361222e81611b11565b61224b5760405163589ed34b60e01b815260040160405180910390fd5b612253613b09565b600061225d612ed6565b9050600061226a8761261d565b905080610100015162ffffff1660001480612283575083155b156122a157604051630713314160e01b815260040160405180910390fd5b6101208101516000906122b99062ffffff168661595e565b90508662ffffff168110156122e157604051630713314160e01b815260040160405180910390fd5b600088336040516020016122f69291906156fe565b6040516020818303038152906040528051906020012060001c90508260c0015160ff1660001461236b5760c08301516000828152600c8601602052604090205460ff9091169061234c9062ffffff8b16906155de565b111561236b57604051635ac0a89b60e11b815260040160405180910390fd5b6000818152600c850160205260408120805462ffffff8b1692906123909084906155de565b90915550600090505b888461012001516123aa9190615972565b62ffffff168110156123e9576123d78888838181106123cb576123cb6156a7565b90506020020135611672565b806123e1816156bd565b915050612399565b50611282898933613683565b60408051808201909152600080825260208201526000612413612ed6565b80549091506001600160401b031683111561244157604051631a3973a960e01b815260040160405180910390fd5b60408051808201825260008581526010939093016020818152928420546001600160a01b038116835295909352918152600160a01b90930462ffffff16928101929092525090565b60008061249461417d565b6000948552602090815260408086206001600160a01b03959095168652939052505090205460ff1690565b6000806124ca612ed6565b80549091506124e790600190600160401b900462ffffff1661599d565b91505090565b606060006124f9612ed6565b9050806002018054610f339061558e565b8161251481613179565b336001600160a01b0384160361253d57604051631eb49d6d60e11b815260040160405180910390fd5b6000612547612ed6565b33600081815260078301602090815260408083206001600160a01b038a1680855290835292819020805460ff1916891515908117909155905190815293945090927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b60006125c48a6123f5565b90506125d58a8a8a8a8a8a886133e2565b6125de81613c22565b6125ed8262ffffff168661363f565b60006125fa8b8787613683565b9050612605816138bf565b6126108b8783613c5e565b5050505050505050505050565b6126256148bf565b600061262f612ed6565b80549091506001600160401b031683111561265d57604051631a3973a960e01b815260040160405180910390fd5b60009283526003016020908152604092839020835161016081018552905462ffffff808216835263010000008204811693830193909352600160301b8104831694820194909452600160481b84048216606082015263ffffffff600160601b850481166080830152600160801b85041660a082015260ff600160a01b8504811660c0830152600160a81b85048116151560e0830152600160b01b85048316610100830152600160c81b8504909216610120820152600160e01b9093041615156101408301525090565b61273d600080516020615b9d833981519152612eb0565b60006127476141a1565b905060005b81548110156127ca5781600001818154811061276a5761276a6156a7565b6000918252602090912001546001600160a01b03908116908416036127b85781600001818154811061279e5761279e6156a7565b600091825260209091200180546001600160a01b03191690555b6127c36001826155de565b905061274c565b508054600181018255600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055565b612815600080516020615b9d833981519152612eb0565b61109f838383613683565b612837600080516020615b9d833981519152612eb0565b61190b6141c5565b836001600160a01b03811633146128595761285933613179565b6128633384613314565b61288057604051631eb49d6d60e11b815260040160405180910390fd5b611a1385858585614212565b6128a3600080516020615b9d833981519152612eb0565b60006128ad614229565b80546001600160a01b0319166001600160a01b03939093169290921790915550565b6000806128da612ed6565b6000848152600382016020908152604091829020825161016081018452905462ffffff8082168352630100000082048116938301849052600160301b82048116948301859052600160481b82048116606084015263ffffffff600160601b830481166080850152600160801b83041660a084015260ff600160a01b8304811660c0850152600160a81b83048116151560e0850152600160b01b83048216610100850152600160c81b8304909116610120840152600160e01b9091041615156101408201529293506129ab919061599d565b62ffffff16949350505050565b6129cf600080516020615b9d833981519152612eb0565b60006129d9612ed6565b60009283526003016020525060409020805460ff60e01b198116600160e01b9182900460ff1615909102179055565b6060612a1382612efa565b612a3057604051630cbdb7b360e41b815260040160405180910390fd5b6000612a3a612ed6565b90506000612a4784612dd4565b5090506000612a558261261d565b90508060e0015115612aa4576000828152600b840160205260409020612a7a8661424d565b604051602001612a8b9291906159b9565b6040516020818303038152906040529350505050919050565b6000828152600b8401602052604090208054612abf9061558e565b80601f0160208091040260200160405190810160405280929190818152602001828054612aeb9061558e565b8015612b385780601f10612b0d57610100808354040283529160200191612b38565b820191906000526020600020905b815481529060010190602001808311612b1b57829003601f168201915b50505050509350505050919050565b612b5e600080516020615b9d833981519152612eb0565b6116346132e4565b611564600080516020615b9d833981519152612eb0565b600080612b88612ed6565b6000938452600401602052505060409020546001600160a01b031661dead1490565b612bb261488a565b6000612bbc613fd5565b9050612bc78661261d565b50600086868686604051602001612be1949392919061566a565b60408051601f19818403018152918152815160209283012060008181529285905290822060018101549193509160ff9091169003612c325760405163c5723b5160e01b815260040160405180910390fd5b6040805160c0810182528254815260019092015460ff8116602084015262ffffff610100820481169284019290925263ffffffff600160201b820481166060850152600160401b8204166080840152600160601b90041660a082015292505050949350505050565b612cb1600080516020615b9d833981519152612eb0565b6000612cbb612ed6565b600981015460405163dfc9f91360e01b81529192506001600160a01b03169063dfc9f91390612cf290309033908790600401615a37565b600060405180830381600087803b158015612d0c57600080fd5b505af1158015611983573d6000803e3d6000fd5b600080612d2b612ed6565b6001600160a01b03948516600090815260079190910160209081526040808320959096168252939093525050205460ff1690565b612d76600080516020615b9d833981519152612eb0565b61190b614103565b612d8661434d565b6001600160a01b038116612dad57604051633a247dd760e11b815260040160405180910390fd5b6110e38161437d565b600080612dc1612ed6565b600d01546001600160a01b031692915050565b6000806000612de1612ed6565b8054909150612dfc90600160401b900462ffffff168561595e565b8154909350612e1790600160401b900462ffffff16846155f6565b612e219085615aba565b915050915091565b612e40600080516020615b9d833981519152612eb0565b60006001600160a01b03821647604051600081818185875af1925050503d8060008114612e89576040519150601f19603f3d011682016040523d82523d6000602084013e612e8e565b606091505b505090508061134557604051630f9310f960e01b815260040160405180910390fd5b612eba8133612489565b6110e357604051623fff3d60e91b815260040160405180910390fd5b7fbc7d0e8ed4dcaf65aa37ff076afe36b4e8fbc0e9b704cfd2ecde67415414d07a90565b6000806000612f0884612dd4565b91509150612f1584612b7d565b15612f24575060009392505050565b6000612f2e612ed6565b60009384526003016020908152604093849020845161016081018652905462ffffff8082168352630100000082048116938301849052600160301b8204811696830196909652600160481b81048616606083015263ffffffff600160601b820481166080840152600160801b82041660a083015260ff600160a01b8204811660c0840152600160a81b82048116151560e0840152600160b01b82048716610100840152600160c81b8204909616610120830152600160e01b900490941615156101409094019390935250111592915050565b60008061300b612ed6565b9050600061301884612dd4565b506000818152600384016020908152604091829020825161016081018452905462ffffff808216835263010000008204811693830193909352600160301b8104831693820193909352600160481b83048216606082015263ffffffff600160601b840481166080830152600160801b84041660a082015260ff600160a01b8404811660c0830152600160a81b84048116151560e0830152600160b01b84048316610100830152600160c81b8404909216610120820152600160e01b909204161580156101408301529192509061316e57600e830154604051633c29490960e21b8152600481018790526000916001600160a01b03169063f0a5242490602401602060405180830381865afa158015613134573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131589190615ad1565b9050801561316c5750600095945050505050565b505b506001949350505050565b6000613183614229565b80549091506001600160a01b03163b15611345578054604051633185c44d60e21b81523060048201526001600160a01b0384811660248301529091169063c617113490604401602060405180830381865afa1580156131e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061320a9190615ad1565b61134557604051631eb49d6d60e11b815260040160405180910390fd5b6000613231612ed6565b6000838152600582016020526040902080546001600160a01b0319166001600160a01b038616908117909155909150829061326b82611ab7565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b60006132af6141a1565b8054600181018255600091825260209091200180546001600160a01b0319166001600160a01b03939093169290921790915550565b60006132ee6143d6565b90503660008037600080366000845af43d6000803e80801561330f573d6000f35b3d6000fd5b600061331f82612efa565b61333c57604051630cbdb7b360e41b815260040160405180910390fd5b600061334783611ab7565b9050806001600160a01b0316846001600160a01b031614806133825750836001600160a01b031661337784610fb7565b6001600160a01b0316145b80611b6d5750611b6d8185612d20565b61339d838383614447565b6133a8600082613227565b80826001600160a01b0316846001600160a01b0316600080516020615bbd83398151915260405160405180910390a4611157838383613d77565b60006133ec612ed6565b905060006133fc89898986612baa565b9050600089336040516020016134139291906156fe565b6040516020818303038152906040528051906020012060001c9050816020015160ff168562ffffff1684600c0160008481526020019081526020016000205461345c91906155de565b111561347b57604051635ac0a89b60e11b815260040160405180910390fd5b606082015163ffffffff16158061349b5750816060015163ffffffff1642105b156134b95760405163589ed34b60e01b815260040160405180910390fd5b608082015163ffffffff16158015906134db5750816080015163ffffffff1642115b156134f95760405163589ed34b60e01b815260040160405180910390fd5b6040516001600160601b03193360601b16602082015260009060340160405160208183030381529060405280519060200120905061356d888880806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250508651915084905061446d565b1580156135ea5750600d8401546040516370a0823160e01b81526001600160a01b03909116906370a08231906135a79033906004016149d1565b602060405180830381865afa1580156135c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e89190615aee565b155b1561360857604051630b094f2760e31b815260040160405180910390fd5b6000828152600c850160205260408120805462ffffff8916929061362d9084906155de565b90915550505050505050505050505050565b60006136528366038d7ea4c680006155f6565b90503461366462ffffff8416836155f6565b11156111575760405163356680b760e01b815260040160405180910390fd5b60008061368e612ed6565b600086815260038201602052604081208054929350916136bb906301000000900462ffffff166001615643565b835462ffffff9190911691506001600160401b03168711156136f057604051631a3973a960e01b815260040160405180910390fd5b62ffffff8616158061370957506001600160a01b038516155b156137275760405163b732d5e160e01b815260040160405180910390fd5b815462ffffff1681111561374e57604051631f6e464360e31b815260040160405180910390fd5b613758878261120e565b825490945062ffffff808216916137789189916301000000900416615643565b62ffffff16111561379c57604051631f6e464360e31b815260040160405180910390fd5b8154869083906003906137bc9084906301000000900462ffffff16615643565b82546101009290920a62ffffff818102199093169190921691909102179055506000848152600484016020526040902080546001600160a01b0319166001600160a01b0387161790556138126008840185614485565b6001600160a01b03851660009081526006840160205260408120805462ffffff891692906138419084906155de565b909155508490505b61385862ffffff8816866155de565b8110156138b45760405181906001600160a01b03881690600090600080516020615bbd833981519152908290a46138a160008783604051806020016040528060008152506144b1565b50806138ac816156bd565b915050613849565b505050509392505050565b60006138c9612ed6565b6009810154604051632e44189760e11b815291925060009182916001600160a01b031690635c88312e906139039030908890600401614bd1565b600060405180830381865afa158015613920573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613948919081019061577f565b8151919350915060005b8181101561198357600061397f34858481518110613972576139726156a7565b60200260200101516145b0565b90506000858381518110613995576139956156a7565b60200260200101516001600160a01b03168260405160006040518083038185875af1925050503d80600081146139e7576040519150601f19603f3d011682016040523d82523d6000602084013e6139ec565b606091505b5050905080613a0e57604051630f9310f960e01b815260040160405180910390fd5b50508080613a1b906156bd565b915050613952565b6000613a2d61417d565b9050613a398383612489565b611157576000838152602082815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339286917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a4505050565b6000613aa161417d565b9050613aad8383612489565b15611157576000838152602082815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4505050565b613b11611aa2565b1561190b5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064015b60405180910390fd5b6000613b60612ed6565b905060ff821615801590613b795750613b776145c9565b155b1561109f5760008433604051602001613b939291906156fe565b60408051601f1981840301815291815281516020928301206000818152600c860190935291205490915060ff841690613bd29062ffffff8716906155de565b1115613bf157604051635ac0a89b60e11b815260040160405180910390fd5b6000818152600c830160205260408120805462ffffff87169290613c169084906155de565b90915550505050505050565b80516001600160a01b03161580613c405750602081015162ffffff16155b156110e3576040516306d423a960e21b815260040160405180910390fd5b6000613c68612ed6565b60008581526010820160205260408120549192506001600160a01b039091169062ffffff85166001600160401b03811115613ca557613ca5615258565b604051908082528060200260200182016040528015613cce578160200160208202803683370190505b50905060005b8562ffffff16811015613d1a57613ceb81866155de565b828281518110613cfd57613cfd6156a7565b602090810291909101015280613d12816156bd565b915050613cd4565b50604051630adf035760e41b81526001600160a01b0383169063adf0357090613d499032908590600401615b07565b600060405180830381600087803b158015613d6357600080fd5b505af1158015611282573d6000803e3d6000fd5b6000613d81612ed6565b90506000613d8e83614078565b9150506000613d9c84611ab7565b9050856001600160a01b0316816001600160a01b031614613dd0576040516313ff771f60e21b815260040160405180910390fd5b6000613ddd8560016155de565b90506000613dea82612dd4565b9150506000613df887612dd4565b506000818152600388016020908152604091829020825161016081018452905462ffffff80821680845263010000008304821694840194909452600160301b8204811694830194909452600160481b81048416606083015263ffffffff600160601b820481166080840152600160801b82041660a083015260ff600160a01b8204811660c0840152600160a81b82048116151560e0840152600160b01b82048516610100840152600160c81b8204909416610120830152600160e01b90049092161515610140830152919250908311801590613ef15750600884811c60009081529088016020526040902054600160ff1b60ff86161c16155b15613f2c576000848152600488016020526040902080546001600160a01b0319166001600160a01b038c16179055613f2c6008880185614485565b6000888152600488016020526040902080546001600160a01b0319166001600160a01b038b16179055858814613f6957613f696008880189614485565b6001600160a01b03891660009081526006880160205260408120805460019290613f949084906155de565b90915550506001600160a01b038a1660009081526006880160205260408120805460019290613fc4908490615aba565b909155505050505050505050505050565b7f5cdb56131f6a8cb8897cc0bafef07a5b2973e186f281253cea0806ea1443c13e90565b614001613b09565b600061400b614054565b805460ff191660011781556040519091507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906140499033906149d1565b60405180910390a150565b7f2ce935bb7ebbf5d9759d0bf10b40148186ea48e69aeea9281cb4f3267f07abf390565b60008061408483612efa565b6140a157604051630cbdb7b360e41b815260040160405180910390fd5b60006140ab612ed6565b90506140b684614636565b600081815260049092016020526040909120546001600160a01b031694909350915050565b60007fcb8952d7e709d77cf862c59597b58044638bae7291440245a00835d98a0e72b36128ad565b600061410d614229565b80546001600160a01b0319166daaeb6d7670e522a718067333cd4e9081178255909150803b1561134557604051633e9f1edf60e11b8152306004820152733cc6cdda760b79bafa08df41ecfa224f810dceb660248201526001600160a01b03821690637d3e3dbe90604401612cf2565b7f8113889f0b868eeca4f3f98876bebc5d45f78186a7ac12c94ed39d8b17ef258e90565b7f92140bce112f095179820a95d551eb064f38e1596fa0b63a05d6960156840a9a90565b6141cd61467b565b60006141d7614054565b805460ff191681556040519091507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906140499033906149d1565b61421d848484613392565b611a13848484846144b1565b7fd1c7a1698d3d2d2fdb5cc2360b499ff16d810b81a494d1feedda8dbe4b67fb7890565b6060816000036142745750506040805180820190915260018152600360fc1b602082015290565b8160005b811561429e5780614288816156bd565b91506142979050600a8361595e565b9150614278565b6000816001600160401b038111156142b8576142b8615258565b6040519080825280601f01601f1916602001820160405280156142e2576020820181803683370190505b5090505b8415611b6d576142f7600183615aba565b9150614304600a86615b2b565b61430f9060306155de565b60f81b818381518110614324576143246156a7565b60200101906001600160f81b031916908160001a905350614346600a8661595e565b94506142e6565b336143566120f1565b6001600160a01b03161461190b57604051636db2465f60e01b815260040160405180910390fd5b60006143876120f1565b9050614392826140db565b816001600160a01b0316816001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000806143e1612ed6565b600f8101549091506001600160a01b03161561440957600f01546001600160a01b0316919050565b4660050361442c5773bb7093937225983269a7003e15a7b8200f8b523d91505090565b73e291354a3aeb7eb49da0f1333d667f17fa33f1c591505090565b61445081613000565b6111575760405163538fd4df60e01b815260040160405180910390fd5b60008261447a85846146c6565b1490505b9392505050565b600881901c600090815260209290925260409091208054600160ff1b60ff9093169290921c9091179055565b60006001600160a01b0384163b156145a857604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906144f5903390899088908890600401615b3f565b6020604051808303816000875af1925050508015614530575060408051601f3d908101601f1916820190925261452d91810190615b72565b60015b61458e573d80801561455e576040519150601f19603f3d011682016040523d82523d6000602084013e614563565b606091505b50805160000361458657604051630568cbab60e01b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611b6d565b506001611b6d565b60006127106145bf83856155f6565b61447e919061595e565b6000806145d46141a1565b905060005b815481101561462d578160000181815481106145f7576145f76156a7565b6000918252602090912001546001600160a01b0316330361461b5760019250505090565b6146266001826155de565b90506145d9565b50600091505090565b600080614641612ed6565b9050600061464e84612dd4565b508254909150611b6d90859061467090600160401b900462ffffff16846155f6565b60088501919061470b565b614683611aa2565b61190b5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401613b4d565b600081815b8451811015611ac3576146f7828683815181106146ea576146ea6156a7565b60200260200101516147b9565b915080614703816156bd565b9150506146cb565b600882811c600081815260208690526040812054909284901c9060ff808716919082181c80156147545761473e816147e8565b60ff168203600885901b1794505050505061447e565b8284101561477557604051630f78a15d60e31b815260040160405180910390fd5b5060001990920160008181526020889052604090205490929080156147b45761479d816147e8565b60ff0360ff16600885901b1794505050505061447e565b614754565b60008183106147d557600082815260208490526040902061447e565b600083815260208390526040902061447e565b60006040518061012001604052806101008152602001615bdd610100913960f87e818283848586878898a8b8c8d8e8f929395969799a9b9d9e9faaeb6bedeeff61483185614852565b02901c81518110614844576148446156a7565b016020015160f81c92915050565b600080821161486057600080fd5b5060008190031690565b604051806040016040528061487d6148bf565b8152602001606081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805161016081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081019190915290565b6001600160a01b03811681146110e357600080fd5b60006020828403121561494257600080fd5b813561447e8161491b565b60005b83811015614968578181015183820152602001614950565b8381111561109f5750506000910152565b6000815180845261499181602086016020860161494d565b601f01601f19169290920160200192915050565b60208152600061447e6020830184614979565b6000602082840312156149ca57600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600080604083850312156149f857600080fd5b8235614a038161491b565b946020939093013593505050565b803562ffffff81168114614a2457600080fd5b919050565b600080600060608486031215614a3e57600080fd5b833592506020840135614a508161491b565b9150614a5e60408501614a11565b90509250925092565b600080600060608486031215614a7c57600080fd5b8335614a878161491b565b92506020840135614a978161491b565b929592945050506040919091013590565b60008060408385031215614abb57600080fd5b50508035926020909101359150565b803560ff81168114614a2457600080fd5b60008083601f840112614aed57600080fd5b5081356001600160401b03811115614b0457600080fd5b6020830191508360208260051b850101111561131d57600080fd5b60008060008060008060008060006101008a8c031215614b3e57600080fd5b89359850614b4e60208b01614aca565b9750614b5c60408b01614a11565b965060608a01356001600160401b03811115614b7757600080fd5b614b838c828d01614adb565b9097509550614b96905060808b01614a11565b935060a08a0135614ba68161491b565b9250614bb460c08b01614a11565b9150614bc260e08b01614a11565b90509295985092959850929598565b6001600160a01b03929092168252602082015260400190565b60008060408385031215614bfd57600080fd5b823591506020830135614c0f8161491b565b809150509250929050565b805162ffffff1682526020810151614c39602084018262ffffff169052565b506040810151614c50604084018262ffffff169052565b506060810151614c67606084018262ffffff169052565b506080810151614c7f608084018263ffffffff169052565b5060a0810151614c9760a084018263ffffffff169052565b5060c0810151614cac60c084018260ff169052565b5060e0810151614cc060e084018215159052565b506101008181015162ffffff81168483015250506101208181015162ffffff8116848301525050610140818101518015158483015261109f565b60208152614d0c602082018351614c1a565b602082015161018082810152600090611b6d6101a0840182614979565b60008083601f840112614d3b57600080fd5b5081356001600160401b03811115614d5257600080fd5b60208301915083602082850101111561131d57600080fd5b803563ffffffff81168114614a2457600080fd5b80151581146110e357600080fd5b6000806000806000806000806000806101208b8d031215614dac57600080fd5b8a356001600160401b03811115614dc257600080fd5b614dce8d828e01614d29565b909b509950614de1905060208c01614a11565b9750614def60408c01614a11565b9650614dfd60608c01614d6a565b9550614e0b60808c01614d6a565b9450614e1960a08c01614aca565b935060c08b0135614e2981614d7e565b9250614e3760e08c01614aca565b9150614e466101008c01614aca565b90509295989b9194979a5092959850565b600080600060608486031215614e6c57600080fd5b83359250614e7c60208501614a11565b91506040840135614e8c8161491b565b809150509250925092565b600080600080600080600060e0888a031215614eb257600080fd5b87359650614ec260208901614aca565b9550614ed060408901614a11565b9450614ede60608901614d6a565b9350614eec60808901614d6a565b925060a08801359150614f0160c08901614a11565b905092959891949750929550565b60008060008060608587031215614f2557600080fd5b8435935060208501356001600160401b03811115614f4257600080fd5b614f4e87828801614adb565b9094509250614f61905060408601614a11565b905092959194509250565b60008060208385031215614f7f57600080fd5b82356001600160401b03811115614f9557600080fd5b614fa185828601614adb565b90969095509350505050565b6000806000806000806000806000806101408b8d031215614fcd57600080fd5b8a359950614fdd60208c01614aca565b9850614feb60408c01614a11565b9750614ff960608c01614aca565b965061500760808c01614a11565b955061501560a08c01614d6a565b945061502360c08c01614d6a565b935060e08b013592506150396101008c01614a11565b9150614e466101208c01614a11565b600081518084526020808501945080840160005b838110156150785781518752958201959082019060010161505c565b509495945050505050565b604080825283519082018190526000906020906060840190828701845b828110156150c55781516001600160a01b0316845292840192908401906001016150a0565b505050838103828501526150d98186615048565b9695505050505050565b600080600080600080608087890312156150fc57600080fd5b86356001600160401b038082111561511357600080fd5b61511f8a838b01614d29565b9098509650602089013591508082111561513857600080fd5b5061514589828a01614d29565b90955093505060408701356151598161491b565b915060608701356151698161491b565b809150509295509295509295565b6000806000806060858703121561518d57600080fd5b8435935061519d60208601614a11565b925060408501356001600160401b038111156151b857600080fd5b6151c487828801614adb565b95989497509550505050565b6000806000604084860312156151e557600080fd5b8335925060208401356001600160401b0381111561520257600080fd5b61520e86828701614d29565b9497909650939450505050565b6000806040838503121561522e57600080fd5b82356152398161491b565b91506020830135614c0f81614d7e565b61016081016112088284614c1a565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b038111828210171561529057615290615258565b60405290565b604051601f8201601f191681016001600160401b03811182821017156152be576152be615258565b604052919050565b600080600080608085870312156152dc57600080fd5b84356152e78161491b565b93506020858101356152f88161491b565b93506040860135925060608601356001600160401b038082111561531b57600080fd5b818801915088601f83011261532f57600080fd5b81358181111561534157615341615258565b615353601f8201601f19168501615296565b9150808252898482850101111561536957600080fd5b808484018584013760008482840101525080935050505092959194509250565b600080600080600080600060e0888a0312156153a457600080fd5b873596506153b460208901614a11565b95506153c260408901614d6a565b94506153d060608901614d6a565b93506153de60808901614aca565b92506153ec60a08901614a11565b915060c08801356153fc81614d7e565b8091505092959891949750929550565b6000806000806080858703121561542257600080fd5b8435935061543260208601614aca565b925061544060408601614a11565b9150614f6160608601614a11565b60006001600160401b0382111561546757615467615258565b5060051b60200190565b803565ffffffffffff81168114614a2457600080fd5b6000602080838503121561549a57600080fd5b82356001600160401b038111156154b057600080fd5b8301601f810185136154c157600080fd5b80356154d46154cf8261544e565b615296565b818152606091820283018401918482019190888411156154f357600080fd5b938501935b838510156155545780858a0312156155105760008081fd5b61551861526e565b85356155238161491b565b8152615530868801615471565b878201526040615541818801615471565b90820152835293840193918501916154f8565b50979650505050505050565b6000806040838503121561557357600080fd5b823561557e8161491b565b91506020830135614c0f8161491b565b600181811c908216806155a257607f821691505b6020821081036155c257634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600082198211156155f1576155f16155c8565b500190565b6000816000190483118215151615615610576156106155c8565b500290565b6000806040838503121561562857600080fd5b82516156338161491b565b6020939093015192949293505050565b600062ffffff808316818516808303821115615661576156616155c8565b01949350505050565b93845260f89290921b6001600160f81b031916602084015260e890811b6001600160e81b0319908116602185015291901b16602482015260270190565b634e487b7160e01b600052603260045260246000fd5b6000600182016156cf576156cf6155c8565b5060010190565b60006001600160401b03838116908316818110156156f6576156f66155c8565b039392505050565b91825260601b6001600160601b031916602082015260340190565b600082601f83011261572a57600080fd5b8151602061573a6154cf8361544e565b82815260059290921b8401810191818101908684111561575957600080fd5b8286015b84811015615774578051835291830191830161575d565b509695505050505050565b6000806040838503121561579257600080fd5b82516001600160401b03808211156157a957600080fd5b818501915085601f8301126157bd57600080fd5b815160206157cd6154cf8361544e565b82815260059290921b840181019181810190898411156157ec57600080fd5b948201945b838610156158135785516158048161491b565b825294820194908201906157f1565b9188015191965090935050508082111561582c57600080fd5b5061583985828601615719565b9150509250929050565b601f82111561115757600081815260208120601f850160051c8101602086101561586a5750805b601f850160051c820191505b8181101561198357828155600101615876565b6001600160401b038311156158a0576158a0615258565b6158b4836158ae835461558e565b83615843565b6000601f8411600181146158e857600085156158d05750838201355b600019600387901b1c1916600186901b178355611a13565b600083815260209020601f19861690835b8281101561591957868501358255602094850194600190920191016158f9565b50868210156159365760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b634e487b7160e01b600052601260045260246000fd5b60008261596d5761596d615948565b500490565b600062ffffff80831681851681830481118215151615615994576159946155c8565b02949350505050565b600062ffffff838116908316818110156156f6576156f66155c8565b60008084546159c78161558e565b600182811680156159df57600181146159f457615a23565b60ff1984168752821515830287019450615a23565b8860005260208060002060005b85811015615a1a5781548a820152908401908201615a01565b50505082870194505b50505050835161566181836020880161494d565b6000606080830160018060a01b03808816855260208188168187015260408481880152838851808652608089019150838a01955060005b81811015615aa95786518051871684528581015165ffffffffffff908116878601529085015116848401529584019591870191600101615a6e565b50909b9a5050505050505050505050565b600082821015615acc57615acc6155c8565b500390565b600060208284031215615ae357600080fd5b815161447e81614d7e565b600060208284031215615b0057600080fd5b5051919050565b6001600160a01b0383168152604060208201819052600090611b6d90830184615048565b600082615b3a57615b3a615948565b500690565b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906150d990830184614979565b600060208284031215615b8457600080fd5b81516001600160e01b03198116811461447e57600080fdfeea8e1b953cb200117b202dd78c6958f9c14d952d5bdaa146141d2a5f9ee220dbddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8a264697066735822122094f5a18949d67f99a8b61c9a18164969a23e742579a40a85088eb229ec7f3f7064736f6c634300080f0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.